有关实体框架+ DDD的问题

时间:2009-10-06 20:36:21

标签: entity-framework domain-driven-design repository-pattern

我很难找到在DDD风格模式中使用EF的直接示例。这也是我第一次使用DDD,并对解决方案布局以及如何使用某些DDD模式提出了一些问题。

1)我见过的大多数关于使用存储库模式w / EF的例子只显示了专门的模型接口,如IContactRepository,然后是实现接口的具体类型。理想情况下,我喜欢使用像IRepository这样的东西,它具有CRUD操作的基本功能集。然后,如果必要,我可以创建专门的存储库,例如IContactRepository:IRepository,因为我的大多数模型都不需要扩展。我吠叫错了树吗?有人可以向我提供这种实施方式的例子吗?

2)现在我将我的解决方案分解为以下三个项目:模型(包含我的EDM),存储库和服务。这是适合还是有其他布局方法我不考虑应该是?

3)我已经看到了具有返回IQueryable的Query(Func< T>)/ Query()方法的存储库的示例。这有点臭吗还是皱眉头?

3 个答案:

答案 0 :(得分:2)

我们目前正在使用带DDD的EF,但我不得不说,在目前的实现中,EF并不适合这种架构。主要问题是EF目前工作的唯一方法是让每个'Entity'派生自EF特定的基类。

另一方面,关于存储库的重点是抽象远离数据访问技术。 DDD背后的整个想法是,域模型应该通过诸如数据访问技术的选择之类的实现细节无约束。这意味着应该定义域对象,使它们是Persistence-Ignorant。

换句话说:您不能将EF'实体'用作域对象,因此在DAL中,您必须手动编写大量代码,这些代码映射到域对象和从EF'实体'映射。这很快就累了。

我肯定会认为在存储库上使用IQueryable是一个漏洞的抽象,并且在DDD用语中它没有多大意义。如果域对象是具有内聚性的单元,那么从它们中仅选择某些“列”并不是很有意义。

在EF for .NET 4.0中,我们将获得Persistence Ignorance,所以它将来会变得更好......

答案 1 :(得分:2)

我想回答#3 ......

我认为它不那么“臭”而且更“懒”。这是我在互联网上看到的一个典型的“存储库”......

public interface IRepository {
  // Query operations.
  IQueryable<T> All<T>();
  IQueryable<T> Find<T>(Expression<Func<T, bool>> expression);
  T Single<T>(Expression<Func<T, bool>> expression);

  // Save operations.
  T Add<T>(T objectToAdd);
  void Delete<T>(T objectToDelete);
  T Update<T>(T objectToUpdate);
}

据我所知,这不是一个存储库,而是一个“会话”或“工作单元”。它是一种方便的方法来抽象出您正在使用的任何数据库技术,而只是与一个非常通用的界面交谈。因此,我们将其重命名为ISession。这是我最近一直在做的模式。

public class PeopleRepository {
  private readonly ISession session;

  public PeopleRepository(ISession session) {
    this.session = session;
  }

  public virtual IEnumerable<Person> Active() {
    return session.Find<Person>(p => p.Active).OrderBy(p => p.LastName).ThenBy(p => p.FirstName);
  }

  public virtual IEnumerable<Person> ByLastName(string name) {
    return session.Find<Person>(p => p.Active && p.LastName.StartsWith(lastName)).OrderBy(p => p.LastName).ThenBy(p => p.FirstName);
  }

  public virtual void DeletePerson(int personId) { 
    // We don't really delete people; we mark them as inactive.
    var person = session.Single<Person>(p => p.Id == personId);
    person.Active = false;
    session.Update(person);
  }
}

在此设置中,ISession是数据存储的通用链接。但是,PersonRepository非常特定于Person对象上的查询和操作类型。

希望这有帮助。

答案 2 :(得分:0)

以下是一个示例:

http://dataguidance.codeplex.com/