2013-02-09 70 views
2

我有一個方法接受輸入參數的列表與添加或更新記錄的交易記錄。實體框架5.0複雜對象的SaveChanges

我循環遍歷列表以發現哪些被修改,並使用以下內容添加: context.Entry(item).State = System.Data.EntityState.Modified; 設置每個事務的狀態。

我遇到的問題是因爲事務對象與TransactionType有關係,而我通過事務的輸入參數列表循環,如果在數據庫中有多個具有相同事務標識的事務我得到以下錯誤:

An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.

  • 通過我使用EF5和代碼第一次的方式。

在關注的方法是:

public TransactionList SaveTransactions(Transaction[] transactions) 
     { 
      try 
      { 
       using (EntityContext context = new EntityContext()) 
       { 
        foreach (var item in transactions) 
        { 
         if (item.TransactionId > 0) 
          context.Entry(item).State = System.Data.EntityState.Modified; 
         else 
          context.Entry(item).State = System.Data.EntityState.Added; 
        } 

        context.SaveChanges(); 
       } 
       return GetLatestTransactions(); 
      } 

## UPDATE ## 如果我設置了TRANSACTIONTYPE每個項目爲空,我不會得到任何錯誤和交易領域的休息將更新正常。即TransAmount,日期等等。問題是,通過將TransType設置爲空,我將永遠不能改變我的交易類型。

using (EntityContext context = new EntityContext()) 
{ 
    foreach (var item in transactions) 
    { 
    //set the fk to null 
    item.TransactionType = null; 

    if (item.TransactionId > 0) 
    { 
     context.Entry(item).State = System.Data.EntityState.Modified; 
    } 
    else 
     context.Entry(item).State = System.Data.EntityState.Added; 
    } 
    context.SaveChanges(); 
} 

## UPDATE 2 ## 我剛剛發現的另一種方式,這會工作,但仍是不理想的我。我得到每件商品的單筆交易,然後設置價值。我不喜歡這個解決方案,因爲.Single將爲每次迭代執行一次往返。

foreach (var item in transactions) 
{ 
    var or = context.Transaction 
    .Include(t => t.Category) 
    .Include(t => t.TransactionReasonType) 
    .Include(t => t.TransactionType) 
    .Single(t => t.TransactionId == item.TransactionId); 

    if (item.TransactionId > 0) 
    { 
    context.Entry(or).CurrentValues.SetValues(item); 
    context.Entry(or).State = System.Data.EntityState.Modified; 
    } 
+0

如果源代碼中有重複,你首先應該解決這個問題。 – 2013-02-09 12:00:31

+0

重複只在外鍵上。即兩個不同的事務可能具有相同的TransactionType。我不會在我的參數或數據庫中多次使用同一個事務鍵。 – 2013-02-09 12:14:25

回答

1

我的問題的解決方案是將添加與更新分開。爲了更新,從數據庫中提取每一行將使用新值設置原始值。添加只需將新值添加到上下文中即可。

foreach (var item in transactions) 
{ 
    if (item.TransactionId > 0) //Update 
    { 
    var original = context.Transaction.Where(
          t => t.TransactionId == item.TransactionId) 
          .FirstOrDefault(); 

    original.TransactionType = context.TypeTransaction.Single(
          p => p.TypeTransactionId == item.TransactionType.TypeTransactionId); 

    context.Entry(original).CurrentValues.SetValues(item); 
    } 
    else //Insert 
    {  
    item.TransactionType = context.TypeTransaction.Single(
          p => p.TypeTransactionId == item.TransactionType.TypeTransactionId); 

    context.Transaction.Add(item); 
    } 
} 

context.SaveChanges(); 
0

另一種方法來解決此問題:

foreach (var item in updated) 
{ 
    var original = db.MyEntities.Find(item.Id); 
    db.Entry(original).CurrentValues.SetValues(item); 
} 
db.SaveChanges();