2016-10-21 4 views
0

Если есть две модели домена клиентов, представляющие различные ограниченные контексты (с разными/перекрывающимися полями), как вы должны обновлять этот определенный ограниченный контекст X Клиент в базе данных, которая может содержать как те, Домены клиентов в одном POCO (или, возможно, Y ограниченном контексте Клиент дополнительно использует список ордеров этого же контекста)?Сопоставление моделей домена DDD с EF POCO

Также я мог бы выразить это так. Как вы решаете случаи, когда модели домена сопоставляют много к одному с базой данных POCO?

Означает ли это, что репозиторий будет запрашивать db еще раз, но на этот раз весь объект POCO из БД, обновить его значения и, наконец, сделать обновление?

+1

В разных контекстах есть своя БД. – plalx

+0

Возможный дубликат [DDD - согласованность объекта в ограниченном контексте и различные схемы в базе данных] (http://stackoverflow.com/questions/34389100/ddd-consistency-of-entity-across-bounded-context-different-schemas- in-databa) – guillaume31

ответ

1

Это поможет, если вы предоставили 2 контекста и перекрывающиеся атрибуты Клиента. Для целей этого ответа я использую контексты: «Продажи» и «Маркетинг» и общий атрибут «Предпочтительное имя»

Моя первоначальная мысль, основанная на фразе «перекрывающиеся поля», заключается в том, что вам нужно вернуться к своей модели так как у вас не должно быть двух моделей, ответственных за конкретное значение, в противном случае у вас есть условия параллелизма/гонки.

Попробуйте и подумайте, как ваши клиенты разрешат ситуацию в старые времена пера. & бумага. Кто будет владеть файлом «клиент»? Будут ли продажи и маркетинг у каждого из них иметь собственную версию, или маркетинг будет полагаться на копию продаж (или наоборот)?

Кроме того, одним из самых мощных аспектов DDD является то, что он заставляет вас упорствовать в том, чтобы выйти в инфраструктурные слои, где они принадлежат. Вам не нужно использовать EF для всех вызовов вашего репозитория, если вам проще обрабатывать некоторые sql для определенного вызова настойчивости, тогда сделайте это.

--Scenario 1: Перекрытие поле не overlapping--

В этом случае эксперты в предметной области пришел к выводу, что Sales.Customer.PreferredName и Marketing.Customer.PreferredName независимые атрибуты и могут быть между контекстами. Маркетинг часто используется поле для их милого мы вам лучшие дружки кампании переписки в том время продаж предпочитала держать на файл наиболее не-неоднозначная таблица базы данных

ЗАКАЗЧИКА имеет 2 поля: PreferredNameSale и PreferredNameMarketing.

В 2 Бетон Хранилища будет в конечном итоге выглядеть примерно так:

class Sales.Repositories.ClientRepository : Domain.Sales.IClientRepository { 
    Update(Domain.Sales.Client salesClient) { 
     using (var db = new MyEfContext()) { 
      var dbClient = db.Client.Fetch(salesClient.Id); 
      dbClient.PreferredNameSales = salesClient.PreferredName; 
      db.SaveChanges(); 
     } 
    } 
} 

class Marketing.Repositories.ClientRepository : Domain.Marketing.IClientRepository { 
    Update(Domain.Marketing.Client marketingClient) { 
     using (var db = new MyEfContext()) { 
      var dbClient = db.Client.Fetch(marketingClient.Id); 
      dbClient.PreferredNameMarketing = marketingClient.PreferredName; 
      db.SaveChanges(); 
     } 
    } 
} 

Entity Framework должны заметить, что только 1 поле было изменено и послать соответствующий update client set field=newvalue where id=1 в базу данных.

Не должно быть проблем с параллелизмом, когда продажи и маркетинг обновляют свою версию одного предпочтительного имени клиентов одновременно.

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

--Scenario 2: Перекрытие поле overlapping--

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

В этом случае есть только одно поле базы данных: client.PreferredName и как с сценарием 1, функции работают на одной и той же таблицы/поля:

class Sales.Repositories.ClientRepository : Domain.Sales.IClientRepository { 
    Update(Domain.Sales.Client salesClient) { 
     using (var db = new MyEfContext()) { 
      var dbClient = db.Client.Fetch(salesClient.Id); 
      dbClient.PreferredName = salesClient.PreferredName; 
      db.SaveChanges(); 
     } 
    } 
} 

class Marketing.Repositories.ClientRepository : Domain.Marketing.IClientRepository { 
    Update(Domain.Marketing.Client marketingClient) { 
     using (var db = new MyEfContext()) { 
      var dbClient = db.Client.Fetch(marketingClient.Id); 
      dbClient.PreferredName = marketingClient.PreferredName; 
      db.SaveChanges(); 
     } 
    } 
} 

Очевидная проблема заключается в том, что сохранить на В то же время, как по продажам, так и по маркетингу, в конечном итоге будет выигрыш с точки зрения сохраненных данных. Вы можете попытаться смягчить это с помощью последних временных меток и т. Д., Но он просто станет более грязным и сломанным. Просмотрите свою модель и помните: DB MODEL! = DOMAIN MODEL! = UI View Model

+0

Очень подробный ответ. Говоря о перекрытии, я имел в виду данные, которые будут использоваться в ограниченных контекстах. Согласно DDD, неплохо сохранить дубликаты полного имени в этих контекстах. Поскольку один из этих контекстов будет отвечать за модерирование полного имени и любого другого контекста, который будет иметь доступ только для чтения, будет в конечном итоге последовательным (события домена). – DasBoot

+0

Ещё один вопрос. Если Marketing.Customer является основным и отвечает за сохранение общих свойств, действительно ли это означает, что при создании Marketing.Customer все остальные БК должны также создавать своего клиента с предоставленной информацией? (это было бы неправильно, потому что отсутствие данных в Sales не должно позволять создавать Sales.Customer без специфических свойств для продажи). Итак, когда и как Sales должен получить эти общие данные. Спасибо за ваши идеи – DasBoot

+0

Вам нужно будет определить «Использовано», я чувствую, что в этом случае это что-то вроде «Мне нужно имя и адрес здесь и здесь», на что я хотел бы спросить «Неужели?» - Продажи звучат так, как будто это можно сделать только с идентификатором клиента. Не путайте потребности своего пользовательского интерфейса с потребностями вашей модели домена, используйте (определённые в домене анемии) представления по мере необходимости. Кроме того, если маркетинг «владеет» данными клиента, он не ограничивает ваш пользовательский интерфейс или приложения, работающие через BC, и использование моделей Marketing.Customer * и репо. – Joe

0
  • Для каждого ограниченного контекста требуется своя база данных. Вот и не должно быть обсуждения здесь. Нарушение этого правила приводит к серьезным последствиям, которые обсуждались много раз.
  • Опасные запахи полей, различные ограниченные контексты имеют разные проблемы и, следовательно, не требуют большого количества данных для обмена. Лучше всего, когда единственное, что вы разделяете, это совокупная идентичность. Если в вашем мире у вас есть один Клиент, который имеет разные проблемы, обрабатываемые двумя различными ограниченными контекстами, вы можете использовать одно значение CustomerId для обоих ограниченных контекстов.

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

+0

Хорошо, я понимаю ваш первый момент. Отдельные базы данных устраняют соблазн и техническую возможность пара BC. Но это только разработчик, чтобы решить, принимает ли он ярлыки. Могут быть и другие более разумные ограничения, чтобы держать все в одной базе данных, но оставлять схемы отдельными и избавляться от вредных привычек. Например, запуск отдельных баз данных в облаке был бы намного более дорогостоящим подходом по сравнению с одним. Конечно, «это зависит», но это всего лишь пример. Я что-то пропустил? – DasBoot

Смежные вопросы