#c# #asp.net-mvc #angularjs #entity-framework
#c# #asp.net-mvc #angularjs #entity-framework
Вопрос:
Я использую Entity Framework (сначала код) для создания базы данных, часть которой содержит две сущности с отношением «многие-ко-многим». Вот их код:
public class Product
{
[Key]
public int ProductId { get; set; }
[MaxLength(50)]
public string CUSIP { get; set; }
[MaxLength(50)]
public string SEDOL { get; set; }
[MaxLength(50)]
public string BUID { get; set; }
[MaxLength(50)]
public string Key { get; set; }
[Required]
public bool Track { get; set; }
[InverseProperty("Products")]
[ForeignKey("ProductListId")]
public virtual List<ProductList> ProductLists { get; set; }
public override string ToString()
{
return String.Format("PRODUCT[ ProductId: {0}, CUSIP: {1}, SEDOL: {2}, BUID: {3}, Key: {4}, Track: {5}, ProductLists: {6} ]",
ProductId,
CUSIP,
SEDOL,
BUID,
Key,
Track,
(ProductLists != null ? "" ProductLists.Count : "null"));
}
}
public class ProductList
{
[Key]
public int ProductListId { get; set; }
[Required]
[MaxLength(50)]
public string Name { get; set; }
[InverseProperty("ProductLists")]
[ForeignKey("ProductId")]
public virtual List<Product> Products { get; set; }
public override string ToString()
{
return String.Format("PRODUCT-LIST[ ProductListId: {0}, Name: {1}, Products: {2} ]",
ProductListId,
Name,
(Products != null ? "" Products.Count : "null"));
}
}
В моем репозитории я пытаюсь написать метод обновления для продукта, такой, чтобы изменение логического значения отслеживания или добавление / удаление его из списка продуктов сохранялось в базе данных. Я использую AngularJS и asp.net-MVC для остальной части моего проекта, поэтому вот метод обновления в классе ProductsController:
public void Put(int id, [FromBody] Product product)
{
_repo.UpdateProduct(id, product);
_repo.Save();
}
Поскольку это вызывается из AngularJS, объект product инициализируется из объекта JS.
И, наконец, вот updateProduct
метод в репозитории:
public bool UpdateProduct(int id, Models.Product product)
{
if (product != null) System.Diagnostics.Debug.WriteLine("UpdateProduct() [" id "]n" product.ToString());
if (id == 0) return AddProduct(product);
try
{
Product ctxProduct = GetProduct(id);
if (ctxProduct != null amp;amp; product != null)
{
ctxProduct.CUSIP = product.CUSIP;
ctxProduct.SEDOL = product.SEDOL;
ctxProduct.BUID = product.BUID;
ctxProduct.Key = product.Key;
ctxProduct.Track = product.Track;
/*ctxProduct.ProductLists = new List<ProductList>();
for (int i = 0; i < product.ProductLists.Count; i )
{
ctxProduct.ProductLists.Add((product.ProductLists[i].ProductListId == 0)
? product.ProductLists[i]
: GetProductListIncludingProducts(product.ProductLists[i].ProductListId));
}*/
return true;
}
return false;
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(e.Message "n ----- " e.InnerException);
return false;
}
}
Прямо сейчас раздел, который должен обновлять отношения ProductList, закомментирован. Пока это так, я могу обновить любое другое поле в продукте, и оно будет работать так, как ожидалось.
Если я раскомментирую этот раздел, код создаст повторяющиеся списки продуктов в базе данных, а также дубликаты всех продуктов, содержащихся в этих списках.
Наконец, если я заменяю GetProductListIncludingProducts(product.ProductLists[i].ProductListId)
на GetProductList(product.ProductLists[i].ProductListId)
, я получаю следующую ошибку из _repo.Save()
:
System.Data.SqlClient.SqlException: Violation of PRIMARY KEY constraint 'PK_dbo.ProductListProducts'. Cannot insert duplicate key in object 'dbo.ProductListProducts'
GetProductListIncludingProducts() просто добавляет .Включить («Продукты») в его вызов контекста.
Я хотел бы, чтобы метод обновления просто перенастроил отношения «многие ко многим» без сбоев или создания большого количества повторяющихся данных.
Ответ №1:
Это заняло некоторое время, но я, наконец, понял это. Оказывается, проблема была в моем форматере WebAPI. В моем коде по умолчанию использовался XMLMediaFormatter — когда я ожидал, что он будет использовать мой JsonMediaFormatter, который я настроил для обработки отслеживания ссылок. На случай, если это кому-нибудь поможет, вот мой окончательный метод UpdateProduct, который работает с JsonMediaFormatter:
public bool UpdateProduct(int id, Product product)
{
if (product != null) System.Diagnostics.Debug.WriteLine("UpdateProduct() [" id "] " product.ToString());
if (id == 0) return AddProduct(product);
try
{
Product ctxProduct = GetProductIncludingProductLists(id);
if (ctxProduct != null amp;amp; product != null)
{
ctxProduct.CUSIP = product.CUSIP;
ctxProduct.SEDOL = product.SEDOL;
ctxProduct.BUID = product.BUID;
ctxProduct.Key = product.Key;
ctxProduct.Track = product.Track;
ctxProduct.ProductLists = new List<ProductList>();
foreach (ProductList pl in product.ProductLists)
ctxProduct.ProductLists.Add(pl.ProductListId == 0
? pl
: GetProductList(pl.ProductListId));
return true;
}
return false;
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine("Update Product Error: " e.Message "nInner: " e.InnerException);
return false;
}
}