2017-06-09 38 views
0

我正在使用實體框架6.當我更新導航屬性到一個對象,然後執行SaveChanges(),而不是引用現有的對象時,它會在引用表中創建一個副本。實體框架 - 斷開連接的上下文和重複記錄

我舉幾個例子如下:

以下示例按預期工作。它創建了一個「客戶」和「訂單」,併成功他們相關聯:

Homer Simpson is buying Duff beer 
ConsoleApplication1.Objects.Customer - Added 
ConsoleApplication1.Objects.Order - Added 

然而,

// Homer Simpson buys some Duff beer 

Console.WriteLine("Homer Simpson is buying Duff beer"); 

Customer customer = new Customer 
{ 
    Name = "Homer Simpson" 
}; 

Order order1 = new Order 
{ 
    Description = "Duff Beer" 
}; 

customer.Orders.Add(order1); 

using (EFContext db = new EFContext()) 
{ 
    db.Customers.Add(customer); 
    DisplayChanges(db); 
    db.SaveChanges(); 
} 

輸出,如果我嘗試再添加一個命令和我現有的客戶聯繫起來,當保存我的改變它複製DB中的客戶對象以及我創造了現有秩序:

// Homer Simpson buys some Duff beer 

Console.WriteLine("Homer Simpson is buying Duff beer"); 

Customer customer = new Customer 
{ 
    Name = "Homer Simpson" 
}; 

Order order1 = new Order 
{ 
    Description = "Duff Beer" 
}; 

customer.Orders.Add(order1); 

using (EFContext db = new EFContext()) 
{ 
    db.Customers.Add(customer); 
    DisplayChanges(db); 
    db.SaveChanges(); 
} 

// Homer Simpson buys some Buzz Cola 

Console.WriteLine("\r\nHomer Simpson is buying Buzz Cola"); 

Order order2 = new Order 
{ 
    Description = "Buzz Cola", 
    Customer = customer 
}; 

using (EFContext db = new EFContext()) 
{ 
    db.Orders.Add(order2); 
    DisplayChanges(db); 
    db.SaveChanges(); 
} 

輸出

Homer Simpson is buying Duff beer 
ConsoleApplication1.Objects.Customer - Added 
ConsoleApplication1.Objects.Order - Added 

Homer Simpson is buying Buzz Cola 
ConsoleApplication1.Objects.Order - Added 
ConsoleApplication1.Objects.Customer - Added 
ConsoleApplication1.Objects.Order - Added 

如果我設置爲相對於導​​航屬性的外鍵,記錄不重複。然而,在這種情況下,我沒有獲得相關對象的屬性,直到我明確地加載:

// Homer Simpson buys some Duff beer 

Console.WriteLine("Homer Simpson is buying Duff beer"); 

Customer customer = new Customer 
{ 
    Name = "Homer Simpson" 
}; 

Order order1 = new Order 
{ 
    Description = "Duff Beer" 
}; 

customer.Orders.Add(order1); 

using (EFContext db = new EFContext()) 
{ 
    db.Customers.Add(customer); 
    DisplayChanges(db); 
    db.SaveChanges(); 
} 

// Homer Simpson buys some donuts 

Console.WriteLine("\r\nHomer Simpson is buying donuts"); 

Order order3 = new Order 
{ 
    Description = "Donuts", 
    CustomerID = 1 
}; 

if (order3.Customer == null) 
{ 
    Console.WriteLine("Customer is null before save!"); 
} 

else 
{ 
    Console.WriteLine("The customer is " + customer.Name + " before save!"); 
} 

using (EFContext db = new EFContext()) 
{ 
    db.Orders.Add(order3); 
    DisplayChanges(db); 
    db.SaveChanges(); 
} 

if (order3.Customer == null) 
{ 
    Console.WriteLine("Customer is null after save!"); 
} 

else 
{ 
    Console.WriteLine("The customer is " + customer.Name + " after save!"); 
} 

using (EFContext db = new EFContext()) 
{ 
    db.Orders.Attach(order3); 
    db.Entry(order3).Reference(x => x.Customer).Load(); 
} 

if (order3.Customer == null) 
{ 
    Console.WriteLine("Customer is null after forced load!"); 
} 

else 
{ 
    Console.WriteLine("The customer is " + customer.Name + " after forced load!"); 
} 

輸出

Homer Simpson is buying Duff beer 
ConsoleApplication1.Objects.Customer - Added 
ConsoleApplication1.Objects.Order - Added 

Homer Simpson is buying donuts 
Customer is null before save! 
ConsoleApplication1.Objects.Order - Added 
Customer is null after save! 
The customer is Homer Simpson after forced load! 

是任何人都能夠提供什麼建議嗎?我明白你可以手動連接和分離實體,但據說,我正在處理一些相當複雜的對象。我想找到一個簡單的方法來控制實體框架中的變更跟蹤。

問候

彼得·迪根

+0

沒有簡單的方法 - 使用斷開的對象圖從未在EF中簡單/簡單。你可以嘗試[GraphDiff](https://github.com/refactorthis/GraphDiff)包,試圖解決這個問題。不幸的是,作者不再支持它。 –

回答

0

當你連接客戶對象訂購二是插入一個新的客戶對象,我想你應該總是使用外鍵而不是附加的實體,和如果您檢查public virtual <T> Add(T entity),您可以看到它返回對象本身,而不包含任何其他對象,則客戶對象將被取消,因此您將無法獲得附加到訂單的客戶對象,因爲您只需將其插入 。不要加載,直到你加載它,這是有道理的,我猜你在你的例子中使用了expl icit加載來加載客戶對象,如果你想避免,你可以啓用延遲加載,並始終獲取客戶對象,而不顯式加載它。簡而言之,總是使用fk,並且當你需要實體加載它時(延遲加載或顯式),附加對象永遠不會是好的做法,除非你想將它們全部插入到一起,或者你不關心重複。 我希望這有助於。