C# 如何将通用存储库与DDD(域模型和持久性模型)一起使用?

C# 如何将通用存储库与DDD(域模型和持久性模型)一起使用?,c#,entity-framework-6,domain-driven-design,repository-pattern,ddd-repositories,C#,Entity Framework 6,Domain Driven Design,Repository Pattern,Ddd Repositories,我有个问题。我们使用的是一个通用存储库,我们的域模型也是持久性模型,但这导致我们对域模型进行了大量调整,以便与ORM保持一致,例如:-我们必须放置一个默认的私有构造函数和一些其他脏的更改,我们正在使用(本例中为实体框架)现在我们决定使用一个不同于富域模型的持久性模型,但在这种情况下我们不能使用通用存储库。 注:我们使用工厂创建域模型,但我们使用AutoMapper将域模型转换为持久性模型。这是一个困难的问题,因为您正试图协调两种对立的方法来实现DDD中的持久性,这两种方法是由相反的思想流派设计的

我有个问题。我们使用的是一个通用存储库,我们的域模型也是持久性模型,但这导致我们对域模型进行了大量调整,以便与ORM保持一致,例如:-我们必须放置一个默认的私有构造函数和一些其他脏的更改,我们正在使用(本例中为实体框架)现在我们决定使用一个不同于富域模型的持久性模型,但在这种情况下我们不能使用通用存储库。
注:我们使用工厂创建域模型,但我们使用AutoMapper将域模型转换为持久性模型。

这是一个困难的问题,因为您正试图协调两种对立的方法来实现DDD中的持久性,这两种方法是由相反的思想流派设计的

一些人认为通用存储库模式是一种新的模式,它可以追溯到DDD的早期采用,当时人们正在寻找工具和技术来简化DDD系统中的持久性。大多数实现最终在通用存储库的契约中公开了ORM查询细节(
IQueryable
,在实体框架的情况下),因为它们是您可以要求回购的各种事情之间的一个方便的共同点

最近的持久性模型方法是朝着相反方向迈出的一步——远离ORM。您要做的是引入一个额外的间接层,使您的域模型(还包括存储库接口)不受持久层特定内容的影响

如果您仍然绝对肯定泛型存储库是通过代码重用获得收益的最佳折衷方案(我建议首先挑战这一点),那么Greg Young是一个合理的折衷方案:

因此,这里的答案是仍然使用通用存储库,但使用 组合而不是继承,并且不将其公开给域作为 合同

您可以利用相同的方法并利用seam将域模型/持久性模型映射加入到混合中

可能(未经测试)符合以下条件:

公共类存储库
{
私有持久存储库innerRepository;
公共Foo GetFooById(int-id)
{
返回MapToDomain(_innerRepository.GetById(id));
}
公共无效添加(Foo-Foo)
{
_Add(MapToPersistence(foo));
}
公共IEnumerable GetByCity(字符串城市)
{
返回_innerRepository.Find(f=>f.City==City);
}
私有Foo映射域(FooPersistence持久化模型)
{
//这里有地图
}
私有FooPersistence映射持久性(Foo-Foo)
{
//这里有地图
}
}
公共类PersistenceRepository,其中T:PersistenceModel
{
公共T GetById(int-id)
{
//...
}
公共无效添加(T)
{
//...
}
公共IQueryable查找(Func谓词)
{
//...
}
}
公共抽象类持久化模型
{
}
公共类FooPersistence:PersistenceModel
{
公共字符串City{get;set;}
}

“在这种情况下,我们不能使用通用存储库”-为什么?为什么你首先需要它?嗨,我需要它来简化开发过程我不需要在每个库中重复相同的代码你不想重复什么代码,你是如何实现的,为什么它与持久性模型不兼容?还有一个例子是,接受谓词的通用要求是伟大的解决方案。我还有另一个问题。如何在这个新的waynote中使用规范模式,规范是一种域模型行为,而不是持久性规范。我想您需要一个
Func
to
Func
mapper。您能用一个例子说明吗?
public class FooRepository
{
    private PersistenceRepository<FooPersistence> _innerRepository;

    public Foo GetFooById(int id)
    {
        return MapToDomain(_innerRepository.GetById(id));
    }

    public void Add(Foo foo)
    {
        _innerRepository.Add(MapToPersistence(foo));
    }

    public IEnumerable<Foo> GetByCity(string city)
    {
        return _innerRepository.Find(f => f.City == city).Select(MapToDomain);
    }

    private Foo MapToDomain(FooPersistence persistenceModel)
    {
        // Mapping stuff here
    }

    private FooPersistence MapToPersistence(Foo foo)
    {
        // Mapping stuff here
    }
}

public class PersistenceRepository<T> where T : PersistenceModel
{
    public T GetById(int id)
    {
        //...
    }

    public void Add(T t)
    {
        //...
    }

    public IQueryable<T> Find(Func<T, bool> predicate)
    {
        //...
    }
}

public abstract class PersistenceModel
{
}

public class FooPersistence : PersistenceModel
{
    public string City { get; set; }
}