ASP.NET MVC中的LINQ to SQL导致DuplicateKeyException

时间:2009-10-21 00:47:50

标签: .net linq-to-sql

我正在关注Pro ASP.NET MVC Framework中的体育商店示例,我得到一个与LINQ相关的异常,我无法弄清楚。完整的代码可以通过网站获得,但这是一个传达问题的片段。

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();
}

在用户界面中,我更新现有产品并单击“保存”,控制器通过调用SaveProduct(产品)来处理帖子 - 其中产品通过参数传递。附加产品时抛出DuplicateKeyException。在调试器中,product参数已初始化,ID为2.

我不希望得到确切的答案,但我希望有人能给我一些提示,说明我可以在哪里解决这个问题。

更新:以下代码有效,但我仍然希望让上面的附加方法正常工作。

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();
}

4 个答案:

答案 0 :(得分:1)

我可能错了,但我认为只有你填充一个对象然后尝试保存它才能得到这个。如果您正在更新现有对象,那么我认为您需要先加载它,使用UpdateModel之类的内容进行更改,然后保存。

然后,L2S知道它正在保存的对象已被加载,并且它是一个更新操作而不是插入。

这对您的问题有意义吗?

答案 1 :(得分:0)

我想通了,但是当他把我放在正确的轨道上时,我正在给出griegs的答案。这是为了防止其他人点击它。我使用SQL Profiler并注意到我在保存时没有看到任何对数据库的命中,甚至没有选择任何记录。

我最终在我的web.config中遇到了一个微不足道的拼写错误,由于行差异,我没有在Beyond Compare中看到...

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

VS

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

如果您没有发现它,生活方式属性拼写错误。存储库是持久的 - 因此数据已按照griegs的建议加载。

答案 2 :(得分: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;
            }
        }
    }
 }

答案 3 :(得分:0)

当我在视图中有ProductID(密钥)时,我也得到了这个,因为我允许VS使用“查看内容:编辑”选项生成视图。 (书中的代码删除了ProductID,但是,我发现最好的学习方法是尝试一下 - 虽然这个错误需要花费几个小时,但这是值得的。)

顺便说一句。好书!