Я хочу использовать объекты EF DbContext/POCO в отдельном режиме, то есть извлекать иерархию объектов из своего бизнес-уровня, вносить некоторые изменения, а затем отправлять всю иерархию обратно в бизнес-уровня, чтобы сохранить базу данных. Каждый вызов BLL использует другой экземпляр DbContext. Чтобы проверить это, я написал код для имитации такой среды.Сложное время с объектами POCO с объектной структурой Entity Framework
Сначала я извлечь Customer
плюс связанные Orders
и OrderLines
: -
Customer customer;
using (var context = new TestContext())
{
customer = context.Customers.Include("Orders.OrderLines").SingleOrDefault(o => o.Id == 1);
}
Следующая добавить новый Order
с двумя OrderLines
: -
var newOrder = new Order { OrderDate = DateTime.Now, OrderDescription = "Test" };
newOrder.OrderLines.Add(new OrderLine { ProductName = "foo", Order = newOrder, OrderId = newOrder.Id });
newOrder.OrderLines.Add(new OrderLine { ProductName = "bar", Order = newOrder, OrderId = newOrder.Id });
customer.Orders.Add(newOrder);
newOrder.Customer = customer;
newOrder.CustomerId = customer.Id;
Наконец я сохраняются изменения (с помощью нового контекст): -
using (var context = new TestContext())
{
context.Customers.Attach(customer);
context.SaveChanges();
}
Я понимаю, что эта последняя часть неполна, поэтому, без сомнения, мне нужно будет изменить состояние новых объектов до вызова SaveChanges(). Добавить или присоединить клиента? Какие сущности я должен изменить?
Прежде чем я смогу добраться до этой стадии, выполнения кода генерирует исключение:
Объект с тем же ключом уже существует в ObjectStateManager.
кажется, проистекает из явно не устанавливать идентификатор двух OrderLine
лиц, так как по умолчанию 0. Я думал, что это было прекрасно, чтобы сделать это, как EF будет обрабатывать вещи автоматически. Я делаю что-то неправильно?
Кроме того, работая над этим «отстраненным» способом, кажется, требуется большая работа, необходимая для установления отношений. Я должен добавить новую структуру заказа в коллекцию customer.Orders
, установить свойство Customer
нового заказа и его CustomerId
собственности. Это правильный подход или есть более простой способ?
Будет ли я лучше смотреть на объекты самоконтроля? Я где-то читал, что они устарели или, по крайней мере, обескуражены в пользу POCOs.
Это что-то для меня, но я все еще не понимаю, какое исключение я получаю. Я не думал, что мне нужно назначать идентификаторы первичного ключа для новых объектов - я думал, что EF позаботился об этом для меня. Или это только в приложенном сценарии? –
Ну, если вы посмотрите на документацию, связанную с ней, метод .Attach() предназначен для существующих объектов NotModified. Если ваши OrderLines являются новыми объектами, то они не соответствуют ни одному из этих критериев. Немодифицированные объекты имеют свой Ключ (обычно .Id), соблюдаемый на пути в базу данных; a 0 вызывает исключение. Таким образом, решение состоит в том, чтобы присоединить их, как указано выше, что заставляет его вставлять их без включения ключа, и, конечно, тогда db устанавливает для вас ключ (снова, .Id), потому что это столбец Identity. В основном .Attach() является довольно запутанным и, вероятно, его следует избегать. –