我正在关注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();
}
答案 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,但是,我发现最好的学习方法是尝试一下 - 虽然这个错误需要花费几个小时,但这是值得的。)
顺便说一句。好书!