Как обновить внуков в совокупном корне - PullRequest
0 голосов
/ 02 марта 2012

Я использую EF Code First, и ленивая загрузка.

Моя проблема связана с тем, как эффективно обновить сущность в коллекции внуков. Прежде всего, я боюсь, что это делает много вызовов в БД, которые на самом деле не нужны. Но если мой класс домена не заботится о сохранности, я не могу найти другой способ сделать это.

Вот классы:

  public class Supplier
 {
  public int Id {get;set;}
  //...Supplier properties

  public virtual ICollection<Contract> Contracts {get;set;} 

  //supplier methods   
 }

 public class Contract
 {
  public int id {get;set;}
  public int SupplierId{get;set;}
  //---Contract properties

  [ForeignKey("SupplierId")]
  public virtual Supplier Supplier {get;set;}
  public virtual ICollection<DeliveryContract> DeliveryContracts {get;set;} 
 }

 public class DeliveryContract
 {
  public int Id {get;set;}
  public bool DeliveryOnMonday{get;set;}
  public bool DeliveryOnTuesday{get;set}
  //...30 different Delivery terms properties

  public Department Department {get;set;}

  public int ContractId {get;set;}
  [ForeignKey("ContractId")
  public virtual Contract Contract {get;set;}
 }

Поставщик - совокупный Корень. Итак, у меня есть метод поставщика, который называется ChangeDeliveryContract, и это соответствует тому, что произошло бы в реальном мире.

public class Supplier
{
 //properties

 public void ChangeDeliveryContract (DeliveryContract cahangedDc)
 {
   //So from the supplier i have to find the contract to change
   var dcToUpdate = Contracts
                    .SingleOrDefault(c=>c.Id == changedDc.ContractId)
                    .SingleOrDefalut(dc=>dc.Id == changedDc.Id);

   //So... what do i do now? Map all 30 properties from changedDc to DcToUpdate
   //Some business rules is also applied here i.e. there can only be one
   // DeliveryContract between Supplier and Department
 }
}

Я использую MVC, чтобы программа выглядела примерно так: общедоступное обновление ActionResult (DeliveryContract updatedDc, int supplierId)

{
  var Supplier = supplierRepository.GetById(supplierid);
  supplier ChangeDeliveryContract (changedDc);
  supplierRepository.Save();

  //More code...
}

Прежде всего, проблема заключается в контракте ChangeDelivery. Я не смог заставить это работать. Кроме того, я чувствую, что запросы к коллекциям могут быть неэффективными. В-третьих, отображение свойств 30+ также кажется немного неправильным.

Как вы, ребята, делаете это, и есть ли здесь лучшие практики.

Ответы [ 3 ]

1 голос
/ 03 марта 2012

При применении DDD выбор совокупных корней может варьироваться в зависимости от различных характеристик модели, которые включают соображения относительно количества дочерних элементов и т. Д. В этом случае, хотя Supplier является AR, это не означает, что DeliveryContract может тоже не АР. Хотя может показаться, что Поставщик является единственным AR, и все операции с поставщиками должны происходить из класса «Поставщик», это может стать неуправляемым в отношении обращений к базе данных, как вы уже поняли. Одной из функций AR является защита инвариантов, и в классе «Поставщик» нет ничего, что использовалось бы для защиты инвариантов , что является возможным признаком того, что Поставщик не является наиболее подходящим AR для реализации требуемых бизнес-правил. Поэтому мне кажется, что в этом случае вы можете создать DeliveryContract AR, со своим собственным репозиторием и методом для применения изменений. Или вы можете заключить Договор AR, в зависимости от того, должен ли договор обеспечивать соблюдение каких-либо инвариантов в отношении договоров поставки, а также от практического рассмотрения количества ожидаемых договоров поставки в контракте. Если число очень велико, то было бы нецелесообразно иметь набор контрактов на поставку для класса контракта. В целом, я бы предпочел иметь меньшие AR, хотя необходимо учитывать инварианты и правила согласованности.

Взгляните на большую серию статей Вона Вернона для углубленного изучения этой темы: Эффективный совокупный дизайн .

1 голос
/ 27 марта 2012

Что касается сопоставления свойств в ChangeDeliveryContract, вы чувствуете, что сопоставление 30 свойств является немного неправильным.Само по себе нет ничего плохого в отображении 30 свойств.Если это должно быть сделано, это должно быть сделано.Вы можете использовать для этого AutoMapper, чтобы упростить задачу.

Я думаю, что «чувство» кода можно изменить, если вы создадите такие методы, как «Supplier.MakeDeliveryOnMonday ()», «Supplier.DontMakeDeliveryOnTuesday ()»,Вы, вероятно, можете догадаться, что делают эти методы (проверьте бизнес-логику и установите логическое значение true или false).Поэтому вам не нужно использовать «большие» методы, такие как ChangeDeliveryContract.

1 голос
/ 02 марта 2012

ОК, это немного сбивает с толку, и я виню в этом смешивание моделей Домена и Постоянства (да, эти учебники по EF сделали БОЛЬШУЮ работу, чтобы запутать всех). Один не должен влиять на другого, поэтому у вас есть шаблон хранилища. И да, домен не должен заботиться о постоянстве.

Теперь, когда Поставщик больше не знает об EF, давайте посмотрим ... Если я правильно понимаю, вам очень нужно изменить дизайн Поставщика (и, вероятно, дочерних агрегатов), потому что вы должны принять во внимание бизнес-правила.

Мне довольно сложно перепроектировать требования из этого кода, но у меня есть ощущение, что у поставщика есть контракты на поставку в разные отделы. При изменении контракта на поставку поставщик должен применять бизнес-правила, действительные в этом контексте (это важно, если для одного и того же объекта существует несколько контекстов).

Я думаю, что контракт на поставку нуждается в некотором уточнении, потому что я не могу поверить, что это всего лишь тупой объект, который имеет только 30 свойств. Возможно, некоторые бизнес-правила связаны с некоторыми свойствами? Итак, нам нужно больше деталей.

В качестве стороны, если вам действительно нужно отобразить 30 свойств, потому что так оно и есть, вы можете использовать Automapper для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...