У меня очень неприятная проблема (для меня в любом случае):
У меня есть простой сценарий, в котором у меня есть объект Product и объект CombinedProduct. Между ними существует много-много связей, поэтому Продукт может принадлежать нескольким Комбинированным продуктам, а Комбинированный продукт может содержать много продуктов.
Сначала я создаю продукт и сохраняю его в базе данных. Позже я создаю CombinedProduct и добавляю этот продукт. Когда я пытаюсь сохранить этот CombinedProduct, сущность продукта снова добавляется в базу данных с помощью Entity Framework вместо простого добавления отношения ... Это действительно сводит меня с ума.
Я уже пытался снова прикрепить продукт к контексту перед сохранением, но Entity жалуется, что у него уже есть продукт с тем же ключом ...
Ниже вы найдете код для всего этого (упрощенный и выделенный код):
Сущность продукта
Public Class SingleProduct
Property SingleProductId As Integer
Property CombinedProducts As ICollection(Of CombinedProduct)
End Class
CombinedProduct
Public Class CombinedProduct
Public Sub New()
Me.Products = New HashSet(Of SingleProduct)()
End Sub
Property CombinedProductId As Integer
Property Products As ICollection(Of SingleProduct)
End Class
Определение отношения многих ко многим
Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)
modelBuilder.Entity(Of CombinedProduct)().
HasMany(Function(c) c.Products).
WithMany(Function(p) p.CombinedProducts).
Map(Sub(m)
m.ToTable("CombinedProductSingleProducts")
m.MapLeftKey("SingleProductId")
m.MapRightKey("CombinedProductId")
End Sub)
End Sub
Код, используемый для сохранения
Using myDataContext As New DataContext
myDataContext.CombinedProducts.Add(product)
myDataContext.SaveChanges()
End Using
Уже пытались подключиться перед сохранением, но это не сработало
For Each prd In product.Products
If myDataContext.Entry(prd).State = EntityState.Detached Then
myDataContext.SingleProducts.Attach(prd)
End If
Next
Одно «решение», которое я нашел, было правильным перед сохранением, очисткой списка продуктов и повторным получением продуктов из базы данных и добавлением их в CombinedProduct, но вряд ли это решение.
Надеюсь, кто-нибудь может мне помочь, это сводит меня с ума!
(Я использую Entity Framework 4.1, с Code First)
Редактировать
Добавление продукта : Это делается в собственном текстовом формате в другой форме:
Using myDataContext As New DataContext
myDataContext.SingleProducts.Add(singleProduct)
myDataContext.SaveChanges()
End Using
Создание комбинированного продукта :
Dim myCombinedProduct = New CombinedProduct
myCombinedProduct.Products.Add(product)
Продукт, который я добавляю, сначала снова выбирается в собственном текстовом формате:
Using myDataContext As New DataContext
Return myDataContext.Products.FirstOrDefault(Function(p) p.ProductId = id)
End Using
Редактировать
Полная история в надежде быть более понятной:
У меня есть приложение winforms с двумя формами: одна для управления продуктами и одна для управления комбинированными продуктами. Приложение N-уровня (пользовательский уровень, бизнес-уровень и уровень данных).
В форме для управления вашими продуктами вы можете просто добавлять / обновлять / удалять продукты. На этой форме все работает отлично.
Другая форма комбинированного продукта:
- при загрузке формы я извлекаю все продукты из базы данных, просматривая бизнес и данные. Функция для извлечения продуктов в слое данных имеет свой собственный DataContext (используя блок). Эта функция возвращает iEnumerable Products.
- Найденные продукты добавляются в ряд комбинированных списков в качестве объектов.
- Вы выбираете продукты, которые хотите добавить в комбинированный продукт, выбирая их
- при сохранении я создаю новый объект CombinedProduct в пользовательском слое, извлекаю объекты продукта из комбинированных списков и добавляю их в новый объект CombinedProduct
- Я отправляю объект CombinedProduct на бизнес-уровень, где выполняю ряд бизнес-правил
- Если все в порядке, комбинированный продукт отправляется на уровень данных, где я пытаюсь снова сохранить его в своем собственном текстовом тексте (using-block).
Итак, у меня есть несколько DataContexts, поскольку они живут и умирают в слое данных.
Надеюсь, это прояснит ситуацию.