Oop 用nhibernate进行域设计
在我的领域中,我有一个叫做Oop 用nhibernate进行域设计,oop,nhibernate,orm,class-design,Oop,Nhibernate,Orm,Class Design,在我的领域中,我有一个叫做Project的东西,它基本上拥有许多简单的配置属性,这些属性描述了当项目执行时应该发生什么。当项目被执行时,它会产生大量的LogEntries。在我的应用程序中,我需要分析给定项目的这些日志条目,因此我需要能够部分连续地从数据库(Oracle)加载部分(时间范围)日志条目。如何将这种关系建模为DB表和对象 我可以有一个Project表和ProjectLog表,并且有一个外键指向Project的主键,在对象级别执行“相同”的操作,有classProject和一个属性 I
Project
的东西,它基本上拥有许多简单的配置属性,这些属性描述了当项目执行时应该发生什么。当项目被执行时,它会产生大量的LogEntries
。在我的应用程序中,我需要分析给定项目的这些日志条目,因此我需要能够部分连续地从数据库(Oracle)加载部分(时间范围)日志条目。如何将这种关系建模为DB表和对象
我可以有一个Project
表和ProjectLog
表,并且有一个外键指向Project
的主键,在对象级别执行“相同”的操作,有classProject
和一个属性
IEnumerable日志项{get;}
让NHibernate做所有的映射。但在这种情况下,我将如何设计ProjectRepository?我可以有一个方法
void FillLog(Project projectToFill、DateTime start、DateTime end)代码>
我如何告诉NHibernate在有人调用此方法之前不应加载日志项,我如何让NHibernate在该方法中加载特定的时间段
我对ORM很陌生,也许这种设计对NHibernate来说不是最优的,或者一般来说?也许我应该以不同的方式设计它?与其将项目实体作为一个实体,为什么不将引用四处移动,让LogEntry
具有产品
属性,并充当一个实体呢
与其将项目实体作为一个实体,为什么不将引用四处移动,并让LogEntry
具有Product
属性,同时作为一个实体
在NHibernate下加载基于部分/过滤/标准的列表的“正确”方法是使用查询。有lazy=“extra”
,但它不能满足您的需要
正如您已经注意到的,这打破了根聚合->子级的DDD模型。我在这个问题上挣扎了一段时间,因为首先我讨厌持久性问题会污染我的域模型,而且我永远无法让API表面看起来“正确”。所属实体类上的筛选器方法可以工作,但还远远不够
最后,我决定用一个名为Query()
的受保护方法扩展我的实体基类(我所有的实体都继承自它,我知道这在现在有点不流行,但它至少让我能够始终如一地做这类事情),该方法采用一个定义关系的LINQ表达式,在存储库的引擎盖下,调用LINQ to NH并返回一个IQueryable
,然后您可以根据需要查询它。然后,我可以在一个常规属性下对该调用进行外观处理
基类执行以下操作:
protected virtual IQueryable<TCollection> Query<TCollection>(Expression<Func<TCollection, bool>> selector)
where TCollection : class, IPersistent
{
return Repository.For<TCollection>().Where(selector);
}
受保护的虚拟IQueryable查询(表达式选择器)
其中t集合:类,IPersistent
{
返回Repository.For().Where(选择器);
}
(这里我应该注意,我的存储库实现直接实现IQueryable
,然后将工作委托给NH会话.Query()
)
facading的工作原理如下:
public virtual IQueryable<Form> Forms
{
get
{
return Query<Form>(x => x.Account == this);
}
}
公共虚拟可查询表单
{
得到
{
返回查询(x=>x.Account==this);
}
}
这将帐户和表单之间的列表关系定义为实际映射关系(表单->帐户)的逆关系
对于“无限”集合(集合中可能有无限数量的对象),这可以正常工作,但这意味着您不能直接在NHibernate中映射关系,因此不能直接在NH查询中使用该属性,只能间接使用
我们真正需要的是替换NHibernate的通用包、列表和集合实现,它知道如何使用LINQ提供程序直接查询列表。一个已被提议作为补丁(请参阅)。正如你所看到的,补丁没有完成或被接受,从我所看到的,提议者没有将其重新打包为一个扩展-迭戈·米耶尔松是这里的一个用户,所以也许他会插话。。。我已经测试了他的建议代码作为一个POC,它确实像广告宣传的那样工作,但显然它没有经过测试或保证,也不一定完整,它可能有副作用,而且没有使用或发布它的许可,你无论如何也不能使用它
除非NH团队着手编写/接受一个补丁来实现这一点,否则我们将不得不继续采取变通办法。NH和DDD对世界的看法存在冲突。在NHibernate下加载部分/过滤/基于标准的列表的“正确”方法是使用查询。有lazy=“extra”
,但它不能满足您的需要
正如您已经注意到的,这打破了根聚合->子级的DDD模型。我在这个问题上挣扎了一段时间,因为首先我讨厌持久性问题会污染我的域模型,而且我永远无法让API表面看起来“正确”。所属实体类上的筛选器方法可以工作,但还远远不够
最后,我决定用一个名为Query()
的受保护方法扩展我的实体基类(我所有的实体都继承自它,我知道这在现在有点不流行,但它至少让我能够始终如一地做这类事情),该方法采用一个定义关系的LINQ表达式,在存储库的引擎盖下,调用LINQ to NH并返回一个IQueryable
,然后您可以根据需要查询它。然后,我可以在一个常规属性下对该调用进行外观处理
基类执行以下操作:
protected virtual IQueryable<TCollection> Query<TCollection>(Expression<Func<TCollection, bool>> selector)
where TCollection : class, IPersistent
{
return Repository.For<TCollection>().Where(selector);
}
受保护的虚拟IQueryable查询(表达式选择器)
其中t集合:类,IPersistent
{
返回Repository.For().Where(选择器);
}
(这里我应该注意,我的存储库实现实现了IQueryable
public virtual IQueryable<Form> Forms
{
get
{
return Query<Form>(x => x.Account == this);
}
}