简体   繁体   English

有关实体框架+ DDD的问题

[英]Questions regarding Entity Framework + DDD

I'm having a difficult time finding straight forward examples of using EF in a DDD style pattern. 我很难找到在DDD风格模式中使用EF的直接示例。 This is also my first time employing DDD and have a few questions regarding solution layout and how to employ some of the DDD patterns. 这也是我第一次使用DDD并且有一些关于解决方案布局以及如何使用一些DDD模式的问题。

1) Most of the examples I've seen regarding using the Repository pattern w/ EF just show specialized Model interfaces such as IContactRepository and then a concrete type implementing the interface. 1)我见过的关于使用存储库模式w / EF的大多数示例只显示了专门的模型接口,如IContactRepository,然后是实现接口的具体类型。 Ideally, I'd love to use something like IRepository that has a basic set of functionality for CRUD ops. 理想情况下,我喜欢使用像IRepository这样的东西,它具有CRUD操作的基本功能集。 I could then create specialized repositories if if necessary such as IContactRepository : IRepository when necesary as most of my models won't need to be extended. 然后,如果必要,我可以创建专门的存储库,例如IContactRepository:IRepository,因为我的大多数模型都不需要扩展。 Am I barking up the wrong tree? 我吠叫错了树吗? Can someone provide me w/ examples of this style of implementation? 有人可以提供这种实施方式的例子吗?

2) Right now I have my solutio broken up into the following three projects: Models (contains my EDM), Repositories, and Services. 2)现在我将我的解决方案分解为以下三个项目:模型(包含我的EDM),存储库和服务。 Is this fitting or is there another layout approach I'm not considering and should be? 这是适合还是有另一种布局方法我不考虑应该是?

3) I've seen examples of repositories having a Query(Func<T>)/Query() methods that return IQueryable. 3)我已经看到了具有返回IQueryable的Query(Func <T>)/ Query()方法的存储库的示例。 Is this smelly or something frowned upon? 这有点臭吗还是皱眉头?

We are currently using EF with DDD, but I would have to say that in its current implementation, EF isn't very suitable to this kind of architecture. 我们目前正在使用EF和DDD,但我不得不说,在目前的实现中,EF不太适合这种架构。 The main problem is that the only way EF currently works is by having each 'Entity' derive from an EF-specific base class. 主要问题是EF当前工作的唯一方法是让每个“实体”派生自EF特定的基类。

On the other hand, the whole point about Repositories is to abstract away the data access technology. 另一方面,关于存储库的全部观点是抽象出数据访问技术。 The whole idea behind DDD is that the Domain Model should be unconstraind by implementation details such as the choice of data access technology. DDD背后的整个想法是,域模型应该不受实施细节的限制 ,例如数据访问技术的选择。 This means that domain objects should be defined so that they are Persistence-Ignorant. 这意味着应该定义域对象,使它们是Persistence-Ignorant。

In other words: You can't use the EF 'Entities' as domain objects, so in your DAL, you must manually write a lot of code that maps to and from the domain objects to the EF 'Entities'. 换句话说:您不能将EF'实体'用作域对象,因此在DAL中,您必须手动编写大量代码,这些代码映射到域对象和从EF'实体'映射。 That gets tired really fast. 这很快就累了。

I would definitely consider having IQueryable on a Repository to be a leaky abstraction, and it doesn't make a lot of sense in DDD parlance. 我肯定会认为在存储库上使用IQueryable是一个漏洞的抽象,并且它在DDD用语中没有多大意义。 If domain objects are cohesive units, it doesn't make a whole lot of sense selecting only certain 'columns' from them. 如果域对象是具有内聚性的单元,那么从它们中仅选择某些“列”并不是很有意义。

In EF for .NET 4.0 we will get Persistence Ignorance, so it should become better in the future... 在EF for .NET 4.0中,我们将获得Persistence Ignorance,因此它将来会变得更好......

I'd like to answer #3... 我想回答#3 ......

I think it's less "smelly" and more "lazy". 我认为它不那么“臭”而且更“懒”。 Here's a typical "repository" that I've been seeing around the internets... 这是我在互联网上看到的一个典型的“存储库”......

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);
}

As far as I'm aware, this is less a repository and more a "session" or "unit of work". 据我所知,这不是一个存储库,而是一个“会话”或“工作单元”。 It's a handy way to abstract away whatever database technology you're using and just talk to an extremely generic interface instead. 它是一种方便的方法来抽象出您正在使用的任何数据库技术,而只是与一个非常通用的界面交谈。 So let's rename it to an ISession , instead. 所以我们将它重命名为ISession This is the pattern I've been doing recently. 这是我最近一直在做的模式。

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);
  }
}

In this setup, the ISession is a generic link to the data store. 在此设置中, ISession是数据存储的通用链接。 The PersonRepository , however, is very specific to the types of queries and actions that are taken on a Person object. 但是, PersonRepository非常特定于在Person对象上执行的查询和操作的类型。

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM