2009-10-21 74 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,但是,我发现最好的学习方法是尝试一下 - 尽管这个错误花费了几个小时,但它是值得的)。

顺便说一句。好书!