У вас здесь происходит пара вещей. Я думаю, что отчасти проблема заключается в том, как вы организовали свой класс переводчиков. Помните, что для сущности вся концепция основана на идентичности экземпляра. Таким образом, Переводчик для сущности не должен возвращать новый объект, он должен возвращать правильный экземпляр объекта. Как правило, это означает, что вы должны сначала предоставить его этому экземпляру.
Возможно, полезно думать об обновлениях по сравнению с созданием нового объекта.
Для обновления я бы структурировал эту операцию следующим образом: у меня был бы веб-сервис, который приложение вызывает для получения и возврата объектов контракта. Этот веб-сервис вызывает и репозитории, и переводчики для выполнения своей работы. Проверка остается на доменном объекте.
В коде обновление будет выглядеть примерно так:
Веб-сервис:
[WebService]
public class OrderService
{
[WebMethod]
public void UpdateOrder(OrderContract orderContract)
{
OrderRepository orderRepository = new OrderRepository(_session);
// The key point here is we get the actual order itself
// and so Customer and all other objects are already either populated
// or available for lazy loading.
Order order = orderRepository.GetOrderByOrderContract(orderContract);
// The translator uses the OrderContract to update attribute fields on
// the actual Order instance we need.
OrderTranslator.OrderContractToOrder(ref order, orderContract);
// We now have the specific order instance with any properties updated
// so we can validate and then persist.
if (order.Validate())
{
orderRepository.Update(order);
}
else
{
// Whatever
}
}
}
Переводчик:
public static class OrderTranslator
{
public static void OrderContractToOrder(ref Order order, OrderContract orderContract)
{
// Here we update properties on the actual order instance passed in
// instead of creating a new Order instance.
order.SetSomeProperty(orderContract.SomeProperty);
// ... etc.
}
}
Ключевой концепцией здесь является то, что у нас есть сущность, мы получаем фактический Order, экземпляр сущности, а затем используем транслятор для обновления атрибутов вместо создания нового экземпляра Order. Поскольку мы получаем исходный Заказ, а не создаем новый экземпляр, возможно, что все ассоциации могут быть либо заполнены, либо заполнены отложенной загрузкой. Нам не нужно воссоздавать какие-либо ассоциации из OrderContract, поэтому проблема устраняется.
Я думаю, что другой частью проблемы может быть ваше понимание того, как проектируется фабрика. Это правда, что для сущностей Фабрика может не устанавливать все возможные атрибуты - метод может стать безнадежно сложным, если он это сделает.
Но что фабрика должна делать, так это создавать все ассоциации для нового объекта, чтобы возвращаемый новый объект находился в действительном состоянии с точки зрения полной и допустимой совокупности. Затем вызывающая сторона может установить все другие различные и различные «простые» атрибуты.
Каждый раз, когда у вас есть Фабрика, вы должны принимать решение о том, какие параметры передавать. Возможно, в этом случае веб-сервис получает фактического Клиента и передает его на завод в качестве параметра. Или, может быть, веб-сервис передает Id, и фабрика отвечает за получение фактического экземпляра Customer. Он будет варьироваться в зависимости от конкретной ситуации, но в любом случае, несмотря на то, что он получает другие требуемые объекты, фабрика должна возвращать как минимум полностью заполненный объект в терминах своего графа, т.е. все отношения должны присутствовать и проходить.
В коде возможный пример создания нового Заказа может быть:
[WebService]
public class OrderService
{
[WebMethod]
public void SaveNewOrder(OrderContract orderContract)
{
// Lets assume in this case our Factory has a list of all Customers
// so given an Id it can create the association.
Order order = OrderFactory.CreateNewOrder(orderContract.CustomerId);
// Once again we get the actual order itself, albeit it is new,
// and so Customer and all other objects are already either populated
// by the factory create method and/or are available for lazy loading.
// We can now use the same translator to update all simple attribute fields on
// the new Order instance.
OrderTranslator.OrderContractToOrder(ref order, orderContract);
// We now have the new order instance with all properties populated
// so we can validate and then persist.
if (order.Validate())
{
//Maybe you use a Repository - I use a unit of work but the concept is the same.
orderRepository.Save(order);
}
else
{
//Whatever
}
}
}
Так, надеюсь, это поможет?