LINQ to SQL in ASP.NET MVC results in a DuplicateKeyException

I follow the Sports Store example in the Pro ASP.NET MVC Framework and I get a LINQ-related exception that I cannot understand. The full code is available through the website, but here is a snippet to convey the problem.

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

In the user interface, I update an existing product and click save, and the controller processes the message by calling SaveProduct (product) - where the product is passed through the parameter. A DuplicateKeyException is thrown at joining a product. In the debugger, the product parameter is initialized and has identifier 2.

I do not expect an exact answer, but I hope someone can give me some clues as to where I can look to solve this problem.

. , , .

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

, , , , , - , . , , , , - UpdateModel, .

L2S , , , , .

?

+1

, griegs, . , , - . SQL Profiler , , .

web.config, Beyond Compare - ...

<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

UpdateCheck ( Attach ) - :

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

I also got this when I had a ProductID (key) in the view that was there because I allowed VS to generate the view using the option "View Content: Edit". (The code in the book is deleted by ProductID, but I believe that the best way to find out is to experiment a bit - and although this error took a couple of hours, it was worth it).

BTW. Great book!

0
source

Source: https://habr.com/ru/post/1720628/


All Articles