0

在我的领域中,我有一个叫做的东西Project,它基本上包含许多简单的配置属性,这些属性描述了项目获取时应该发生的事情executed。当项目被执行时,它会产生大量的LogEntries. 在我的应用程序中,我需要分析给定项目的这些日志条目,因此我需要能够从数据库 (Oracle)部分连续加载一部分(时间范围)日志条目。您如何将这种关系建模为数据库表和对象?

我可以有一个Project表和一个表,ProjectLog并有一个主键的外键,Project并在对象级别做“相同”的事情有类Project和一个属性

IEnumerable<LogEntry> LogEntries { get; }

并让 NHibernate 完成所有映射。但是在这种情况下我将如何设计我的 ProjectRepository 呢?我可以有一个方法

void FillLog(Project projectToFill, DateTime start, DateTime end);

我如何告诉 NHibernate 在有人调用此方法之前它不应该加载 LogEntries,我如何让 NHibernate 在该方法中加载特定的时间范围?

我对 ORM 很陌生,也许这种设计对于 NHibernate 或一般来说不是最佳的?也许我应该以不同的方式设计它?

4

2 回答 2

2

与其将 Project 实体作为聚合根,不如移动引用并让其LogEntry拥有一个Product属性并充当聚合根

public class LogEntry
{
    public virtual Product Product { get; set; }
    // ...other properties
}

public class Product
{
    // remove the LogEntries property from Product
    // public virtual IList<LogEntry> LogEntries { get; set; }
}

现在,由于这两个实体都是聚合根,因此您将拥有两个不同的存储库:ProductRepositoryLogEntryRepository. LogEntryRepository可以有一个方法GetByProductAndTime

IEnumerable<LogEntry> GetByProductAndTime(Project project, DateTime start, DateTime end);
于 2012-06-19T16:06:44.707 回答
1

在 NHibernate 下加载部分/过滤/基于标准的列表的“正确”方式是使用查询。有,lazy="extra"但它不做你想要的。

正如您已经注意到的那样,这打破了根聚合 -> 子级的 DDD 模型。我一直在为这个问题苦苦挣扎,因为首先我讨厌持久性问题污染我的域模型,而且我永远无法让 API 表面看起来“正确”。拥有实体类的过滤器方法工作但远非漂亮。

最后,我决定扩展我的实体基类(我的所有实体都继承自它,我知道这些天有点不合时宜,但它至少让我可以始终如一地做这种事情)使用一个名为Query<T>()LINQ的受保护方法定义关系的表达式,并在存储库的底层调用 LINQ-to-NH 并返回一个IQueryable<T>您可以根据需要查询的值。然后,我可以在常规属性下方调用该调用。

基类这样做:

protected virtual IQueryable<TCollection> Query<TCollection>(Expression<Func<TCollection, bool>> selector)
        where TCollection : class, IPersistent
    {
        return Repository.For<TCollection>().Where(selector);
    }

(我应该在这里注意到我的 Repository 实现IQueryable<T>直接实现,然后将工作委托给 NH Session.Query<T>()

外墙的工作方式是这样的:

public virtual IQueryable<Form> Forms 
{ 
    get 
    { 
         return Query<Form>(x => x.Account == this); 
    } 
}

这将 Account 和 Form 之间的列表关系定义为实际映射关系的逆(Form -> Account)。

对于“无限”集合 - 集合中可能存在无限数量的对象 - 这可以正常工作,但这意味着您不能直接在 NHibernate 中映射关系,因此不能直接在 NH 查询中使用该属性,只有间接地。

我们真正需要的是替代 NHibernate 的通用包、列表和集合实现,这些实现知道如何使用 LINQ 提供程序直接查询列表。一个已被提议作为补丁(参见https://nhibernate.jira.com/browse/NH-2319)。正如您所看到的,补丁尚未完成或被接受,并且从我所看到的提议者没有将其重新打包为扩展 - Diego Mijelshon 是这里的用户所以也许他会插话......我有将他提议的代码作为 POC 进行了测试,它确实像宣传的那样工作,但显然它没有经过测试或保证或不一定完整,它可能有副作用,并且未经许可使用或发布它,你无论如何都不能使用它。

直到并且除非 NH 团队开始编写/接受使这种情况发生的补丁,否则我们将不得不继续诉诸变通方法。NH 和 DDD 只是对世界的看法相互矛盾,在这里。

于 2012-06-20T12:33:11.807 回答