存储库添加和创建方法

Ser*_*gio 5 domain-driven-design data-access-layer ddd-repositories repository-pattern

为什么存储库的.Add方法通常实现为接受要添加的实体实例,并且.Id已经“设置”(尽管可以通过反射再次设置),这应该是存储库的责任?
实现它不是更好.CreateAndAdd吗?

例如,给定一个Person实体:

public class Person
{
    public Person(uint id, string name)
    {
        this.Id = id;
        this.Name = name;
    }

    public uint Id { get; }
    public string Name { get; }
}
Run Code Online (Sandbox Code Playgroud)

为什么存储库通常实现为:

public interface IRpository<T>
{
    Task<T> AddAsync(T entity);
}
Run Code Online (Sandbox Code Playgroud)

而不是:

public interface IPersonsRpository
{
    Task<Person> CreateAndAddAsync(string name);
}
Run Code Online (Sandbox Code Playgroud)

Voi*_*son 6

为什么存储库通常被实现为...?

有几个原因。

从历史上看,domain-driven-design它深受介绍该术语的埃里克·埃文斯 (Eric Evans) 著作的影响。在那里,埃文斯提出存储库提供集合语义,提供“内存中集合的幻觉”。

添加 a String,甚至 a Name,到集合中Person没有多大意义。

更广泛地说,弄清楚如何从一组参数重建实体是与存储分开的责任,因此也许去那里没有意义(注意:存储库通常最终负责从参数中重建实体)一些存储的纪念品,所以它并不是完全陌生的,但通常有一个额外的抽象,即“工厂”,真正完成工作。)

使用通用存储库接口通常很有意义,因为通过检索/存储操作与集合中的各个元素进行交互不需要大量的自定义操作。存储库可以支持对不同类型实体的自定义查询,因此专门调用它会很有用

public interface IPersonRepository : IRepository<Person> {
    // Person specific queries go here
}
Run Code Online (Sandbox Code Playgroud)

最后,id……事实是,身份作为一个概念,包含了很多“视情况而定”的内容。在某些情况下,存储库为实体分配 id 可能是有意义的——例如,使用数据库生成的唯一键。通常,您会希望控制存储库外部的标识符。课程用马。

  • 如果我想使用增量 `int` 作为 `Id` 怎么办?谁能够在插入实体之前生成有效的实体? (2认同)