通过存储库仅保留大型实体的一部分

发布于 2024-12-18 16:30:11 字数 1026 浏览 2 评论 0原文

我有一个实体,它是一个聚合根并包含很多子实体。基本上,从数据库加载它并持久化它是一个非常昂贵的操作。大多数时候,我只更改实体的一小部分,因此确实不需要加载和持久化整个实体。然而,我不确定如何使用 DDD 原则和存储库模式来实现这一点。

我一直在考虑这样的问题:

interface IAggregateRoot {
    string Id { get; }

    ISubEntityA EntityA { get; }
    IList<ISubEntityB> EntityB { get; }
}

interface ISubEntityA {
    string Id { get; }

    int Foo { get; set; }
}

interface ISubEntityB {
    string Id { get; }

    string Bar { get; set; }
}

interface IRepository {
    IAggregateRoot Get(string rootId);
    ISubEntityA Get(string rootId);
    IList<ISubEntityB> Get(string rootId, int offset, int pageSize, out int numPages);

    ISubEntityB Find(string rootId, some specification to select a single ISubEntityB);

    // I can update either the entire aggregate root or an individual sub entity using
    // these methods.
    void AddOrUpdate(IAggregateRoot root);
    void Update(string rootId, ISubEntityA a);
    void Update(string rootId, ISubEntityB b);
}

这种方法有什么问题吗?关于这个“问题”有最佳实践吗?

I have an entity which is an aggregate root and contains a lot of sub-entities. Basically, loading it from the database and persisting it all is a very expensive operation. Most of the time, I only change small parts of the entity so there really is no need to load and persist the entire entity anyway. I am, however, not sure how to implement this using DDD principles and the repository pattern.

I have been considering something like:

interface IAggregateRoot {
    string Id { get; }

    ISubEntityA EntityA { get; }
    IList<ISubEntityB> EntityB { get; }
}

interface ISubEntityA {
    string Id { get; }

    int Foo { get; set; }
}

interface ISubEntityB {
    string Id { get; }

    string Bar { get; set; }
}

interface IRepository {
    IAggregateRoot Get(string rootId);
    ISubEntityA Get(string rootId);
    IList<ISubEntityB> Get(string rootId, int offset, int pageSize, out int numPages);

    ISubEntityB Find(string rootId, some specification to select a single ISubEntityB);

    // I can update either the entire aggregate root or an individual sub entity using
    // these methods.
    void AddOrUpdate(IAggregateRoot root);
    void Update(string rootId, ISubEntityA a);
    void Update(string rootId, ISubEntityB b);
}

Are there any problems with this approach? Is there a best practice regarding this "problem"?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

横笛休吹塞上声 2024-12-25 16:30:11

我使用类似的技术。例如,假设我激活一个帐户:

var account = repository.Get(accountId);

account.Activate();

repository.AccountActivated(); // or repository.SaveActivationDetails()

由于您不希望您的存储库涉及域行为,因此您不会执行以下操作:

repository.ActivateAccount(account);

但您可以这样做:

account.Activate(repository); // in the Activate method the relevant repository 
                              // persistence method will be invoked.

因此您可以选择一种您喜欢的机制。

但回到你的存储库:我不会进行查询。轻量级查询层可以返回像 DataTable 这样简单的东西供前端使用;其他 DTO。这与您去那里的寻呼有关。

I use a similar technique. For instance, say I activate an account:

var account = repository.Get(accountId);

account.Activate();

repository.AccountActivated(); // or repository.SaveActivationDetails()

Since you don't want your repository involved with domain behaviour your wouldn't do the following:

repository.ActivateAccount(account);

But you could do this:

account.Activate(repository); // in the Activate method the relevant repository 
                              // persistence method will be invoked.

So you can choose a mechanism you are comfortable with.

But getting back to your repository: I wouldn't do querying. A lightweight query layer can return something as simple as a DataTable for your front-end to consume; else DTOs. This relates to the paging you have going there.

晌融 2024-12-25 16:30:11

该存储库仅处理聚合根,而不处理其部分。所以我建议这个

interface IRepository {
IAggregateRoot Get(string rootId);
//ISubEntityA Get(string rootId); <- this you get from the AR
//IList<ISubEntityB> Get(string rootId, int offset, int pageSize, out int numPages);
 //for the method above I suggest a different repository and model dedicated for view

// ISubEntityB Find(string rootId, some specification to select a single ISubEntityB);

// I can update either the entire aggregate root or an individual sub entity using
// these methods.
void Save(IAggregateRoot root); // repository should know if to insert or update, by comparing to the existing instance, use of an OR\M recommended
//    void Update(string rootId, ISubEntityA a); <- this should be handled by the method above
//  void Update(string rootId, ISubEntityB b); <- this too
}

The repository deals only with aggregates roots and not with parts of it. SO I suggest this

interface IRepository {
IAggregateRoot Get(string rootId);
//ISubEntityA Get(string rootId); <- this you get from the AR
//IList<ISubEntityB> Get(string rootId, int offset, int pageSize, out int numPages);
 //for the method above I suggest a different repository and model dedicated for view

// ISubEntityB Find(string rootId, some specification to select a single ISubEntityB);

// I can update either the entire aggregate root or an individual sub entity using
// these methods.
void Save(IAggregateRoot root); // repository should know if to insert or update, by comparing to the existing instance, use of an OR\M recommended
//    void Update(string rootId, ISubEntityA a); <- this should be handled by the method above
//  void Update(string rootId, ISubEntityB b); <- this too
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文