2009-10-21 69 views
3

我正在關注Pro ASP.NET MVC Framework中的體育商店示例,並且我收到了一個與我找不到的LINQ相關的異常。完整的代碼可通過網站獲得,但這裏是傳達問題的片段。LINQ to SQL ASP.NET MVC中的結果DuplicateKeyException

private Table<Product> productsTable; 
// ... 
public void SaveProduct(Product product) { 
    if (product.ProductID == 0) 
    productsTable.InsertOnSubmit(product); 
    else { 
    productsTable.Attach(product); 
    productsTable.Context.Refresh(RefreshMode.KeepCurrentValues, product); 
    } 
    productsTable.Context.SubmitChanges(); 
} 

在UI,我更新現有的產品,然後單擊保存和控制器通過調用SaveProduct(產品)處理後 - 其中,產品是通過參數傳遞。附加產品時會引發DuplicateKeyException。在調試器中,產品參數被初始化並且ID爲2.

我不期待確切的答案,但我希望有人可以給我一些提示,以瞭解我在哪裏可以解決這個問題。

UPDATE:下面的代碼工作,但我仍然希望得到上面的附加方法工作。

public void SaveProduct(Product product) { 
    if (product.ProductID == 0) 
    productsTable.InsertOnSubmit(product); 
    else { 
    Product p2 = productsTable.Single(em => em.ProductID == product.ProductID); 
    p2.Name = product.Name; 
    p2.Description = product.Description; 
    p2.Price = product.Price; 
    p2.Category = product.Category; 
    } 
    productsTable.Context.SubmitChanges(); 
} 
+0

聽起來像它可能試圖做一個INSERT,當它應該做一個更新。您可以更新產品2,但不能插入另一個。 – DOK 2009-10-21 00:52:58

回答

1

我可能是錯的,但我認爲唯一一次你可以得到這個是如果你填充一個對象,然後嘗試保存它。如果您正在更新現有對象,那麼我認爲您需要先加載它,然後使用類似UpdateModel的方式進行更改,然後保存。

L2S然後知道它正在保存的對象已被加載,並且它是一個更新操作而不是插入。

這對您的問題有意義嗎?

+0

我嘗試使用Linq檢索產品,使用參數的屬性更新其屬性,並調用submitchanges並使其工作。不過,我希望能讓作者的附加方法起作用。我會看看我是否可以玩弄它,但我可能只需要接受它不適合我。 – Mayo 2009-10-21 01:12:03

+0

您不需要接受它不起作用。有一個原因,它不工作,一旦你發現....這聽起來像你加了兩次相同的記錄,因此消息。如果你在更新之前清除你的id字段,並且你得到一個新的記錄,這可能是發生了什麼。試圖想想你可以做的事情來測試實際發生的事情。 – griegs 2009-10-21 01:17:22

0

我想通了,但是我給了格里格斯的答案,因爲他讓我走上正軌。這是爲了防止其他人擊中它。我使用了SQL Profiler,並注意到在保存時我沒有看到數據庫的任何命中,甚至沒有選擇任何記錄。

我終於跨過我的web.config微乎其微的錯字,我沒有在除了看到比較由於線路的差異來......

<component id="ProdsRepository" service="DomainModel.Abstract.IProductsRepository, DomainModel" type="DomainModel.Concrete.SqlProductsRepository, DomainModel" lifesyle="PerWebRequest"> 

<component id="ProdsRepository" service="DomainModel.Abstract.IProductsRepository, DomainModel" type="DomainModel.Concrete.SqlProductsRepository, DomainModel" lifestyle="PerWebRequest"> 

萬一你不會發現它,生活方式屬性拼寫錯誤。該存儲庫持續存在 - 因此數據已按照griegs的建議加載。

+0

另一種生活方式。 – flipdoubt 2010-02-09 20:00:30

0

你可以在你的對象改變UpdateCheck的屬性決不(它使安裝工作),或使用財產以後這樣的:

public void SaveProduct(Product product) 
{ 
    if (product.ProductID == 0) 
    productsTable.InsertOnSubmit(product); 
    else 
    { 
    Product old = productsTable.Single(em => em.ProductID == product.ProductID); 
    ApplyChanges(ref old, product); 
    } 
    productsTable.Context.SubmitChanges(); 
} 

private static void ApplyChanges<T>(ref T Original, T Changes) 
{ 
    Type OriginalType = typeof(T); 

    PropertyInfo[] Info = OriginalType.GetProperties(); 

    foreach (PropertyInfo PI in Info) 
    { 
     foreach (Attribute attr in Attribute.GetCustomAttributes(PI)) 
     { 
      // Check for the Column attribute. 
      if (attr.GetType() == typeof(System.Data.Linq.Mapping.ColumnAttribute)) 
      { 
       if(((attr as System.Data.Linq.Mapping.ColumnAttribute).IsDbGenerated == false) && PI.CanWrite) 
       { 
        PI.SetValue(Original, PI.GetValue(Changes, null), null); 
       } 
       break; 
      } 
     } 
    } 
} 
0

我也有這個時候,我有產品ID(關鍵),因爲我允許VS用「查看內容:編輯」選項生成視圖。 (本書中的代碼已經刪除了ProductID,但是,我發現最好的學習方法是嘗試一下 - 儘管這個錯誤花費了幾個小時,但它是值得的)。

順便說一句。好書!