我想以分離方式使用EF DbContext/POCO實體,即從我的業務層中檢索實體層次結構,進行一些更改,然後將整個層次結構發送回業務層保留回數據庫。每個BLL調用使用DbContext的不同實例。爲了測試這個,我編寫了一些代碼來模擬這樣的環境。使用實體框架分離POCO對象困難時期
首先,我檢索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
實體的ID來幹,這樣既默認爲0。我認爲這是很好做到這一點作爲EF將自動地處理事情。難道我做錯了什麼?
此外,以這種「分離」方式工作,似乎需要很多工作來建立關係 - 我必須將新訂單實體添加到customer.Orders
集合,設置新訂單的Customer
屬性,以及其CustomerId
屬性。這是正確的方法還是有一個更簡單的方法?
查看自我跟蹤實體會更好嗎?我會在某個地方看到它們被棄用,或者至少不贊成POCO。
這是我想看的東西,但我仍然不明白我得到的異常。我不認爲我必須將主密鑰ID分配給新實體 - 我認爲EF爲我處理了這個問題。或者只有在附帶的情況下? –
好吧,如果你看看我在那裏鏈接的文檔,.Attach()方法適用於現有的NotModified實體。如果您的OrderLines是新對象,則它們不符合這些條件。 NotModified對象的Key(通常是.Id)在進入數據庫的過程中被授予; 0導致異常。所以解決方法是像上面那樣附加它們,這會導致它插入它們而不包含Key,當然,db會爲你設置Key(同樣是.Id),因爲它是一個Identity列。基本上.Attach()有點令人困惑,應該避免。 –