Сохранение только частей больших объектов через хранилище - PullRequest
1 голос
/ 28 ноября 2011

У меня есть объект, который является совокупным корнем и содержит множество дочерних объектов. По сути, загрузка из базы данных и сохранение всего этого - очень дорогая операция. Большую часть времени я изменяю только небольшие части сущности, поэтому в действительности нет необходимости загружать и сохранять всю сущность в любом случае. Однако я не уверен, как реализовать это, используя принципы 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);
}

Есть ли проблемы с этим подходом? Есть ли лучшая практика в отношении этой «проблемы»?

Ответы [ 2 ]

1 голос
/ 28 ноября 2011

Я использую подобную технику. Например, скажем, я активировал аккаунт:

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, для использования вашим внешним интерфейсом; еще DTOs. Это относится к пейджингу, который вы там посещаете.

0 голосов
/ 16 февраля 2012

Репозиторий имеет дело только с корнями агрегатов, а не с его частями. Поэтому я предлагаю это

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
}
...