我很难找到在DDD风格模式中使用EF的直接示例。这也是我第一次使用DDD,并对解决方案布局以及如何使用某些DDD模式提出了一些问题。
1)我见过的大多数关于使用存储库模式w / EF的例子只显示了专门的模型接口,如IContactRepository,然后是实现接口的具体类型。理想情况下,我喜欢使用像IRepository这样的东西,它具有CRUD操作的基本功能集。然后,如果必要,我可以创建专门的存储库,例如IContactRepository:IRepository,因为我的大多数模型都不需要扩展。我吠叫错了树吗?有人可以向我提供这种实施方式的例子吗?
2)现在我将我的解决方案分解为以下三个项目:模型(包含我的EDM),存储库和服务。这是适合还是有其他布局方法我不考虑应该是?
3)我已经看到了具有返回IQueryable的Query(Func< T>)/ Query()方法的存储库的示例。这有点臭吗还是皱眉头?
答案 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)
以下是一个示例: