2012-08-03 68 views
0

我在玩Entity Framework,並且遇到了多對多映射的絆腳石。 可以說我有兩個實體,訂單和產品。EF Code First:保存複製數據(多對多)

裏面我Order實體我有:

int OrderID, 
double OrderPrice 
datetime OrderDate 
ICollection<Product> Products 
datetime DispactDate 

等等...

然後我的產品類中我有

int ProductID 
string ProductName 
string ProductDescription 

等。

在我的Code First EF DB中,我有一張訂單表,它可以很好地映射到我的訂單上,產品表中包含可以訂購的產品清單,然後使用EF代碼優先遷移EF創建帶有外鍵的OrderProducts其他表的主鍵。都好。

但是,當我去保存在其產品集合中有多個產品的訂單時,EF將複製Product表中的所有條目。因此,如果我添加產品10,13,它會創建三個帶有三個新ID的新行並映射到它們,而不是原件。如果我再用另外20個現有產品處理另一個訂單,則會在產品表中製作20個新條目!

在我的DbContext我已經覆蓋了onModelCreatingEvent:

modelBuilder.Entity<Order>() 
       .HasMany(x=>x.Products) 
       .WithMany() 
       .Map(be => 
        { 
         be.ToTable("OrderProducts"); 
       }); 

我猜的東西是配置錯在這裏。我從How to map many-to-many relationships in Entity Framework CTP5?

以前我有兩個單獨的存儲庫 - 一個用於訂單,一個用於產品。我現在將它們合併到了公開訂單和產品的orderRepository中,以便我可以將產品附加到orderRepository上下文中。 要生成的產品,我有一個控制器行動AddProducts:

public RedirectToRouteResult Products(FormCollection selectedProducts) 
     { 
       currentOrder.Products = new List<Product>(); 
       foreach (string thisProduct in selectedProducts) 
       { 
        int thisProductID = int.Parse(thisProduct); 
        Product selectedProduct = orderRepository.Products.Where(e => e.ProductID == thisProductID).FirstOrDefault(); 

        if (selectedProduct != null) 
        { 
         orderRepository.AttachToContext(selectedProduct); 
         currentOrder.Products.Add(selectedProduct); 
        }      
       } 

       orderRepository.saveChanges(currentOrder); 

}

+0

你可以發佈你找到的代碼並將產品添加到訂單中嗎? – 2012-08-03 13:07:01

+0

增加了我在做Luke的例子。 – LDJ 2012-08-03 16:40:11

回答

0

你可以敲一點點單元測試,只是創建上下文,檢索產品,創建一個訂單,並將檢索到的產品添加到訂單?

這應該工作得很好。這聽起來像你正在創建一個新的產品對象,而不是使用預先存在的對象。或者創建一個,而不是設置適當的實體鍵。

聽起來好像你從不同的上下文中得到它,因爲你通常會得到一個警告,說明它已經連接到另一個上下文。

1

我懷疑在orderRepository你有比ProductsRepo不同的上下文實例。您應該首先將attach的產品發送到ProductsorderRepository的上下文中。

順便說一句,這就是爲什麼每個實體的存儲庫可以真正得到解決的一個例子。如果您想使用存儲庫模式,那麼在聚合根中思考通常會更好。

+0

是的,這也是我的懷疑 – 2012-08-04 00:32:55

+0

似乎沒有幫助。 currentOrder.Products.Add之前的行(selectedProduct);我添加了ProductsRepo.AttachToContext(selectedProduct),它只是簡單地處理context.Products.Attach(product);但值仍然是重複的。 – LDJ 2012-08-04 07:36:32

+0

您必須附加到訂單存儲庫中的上下文。 – 2012-08-04 18:26:36

0

謝謝。管理解決這個問題。在我的OrderRepository中,我不得不用EntitySate.Unchanged狀態手動標記每個Product。因此,在SaveOrder()我現在做的事:

foreach (Product product in Orders.Products) 
{ 
    context.Entry(product).State = System.Data.EntityState.Unchanged; 
} 

這是工作正常,但我很好奇,爲什麼我不得不做這一步時,順序內的每個產品有一個有效的(老)產品ID已經被分配到它? 奇怪。