Ответ 1
Чтобы создать отношение "многие ко многим" с базовым подходом, вам необходимо настроить схему базы данных, которая следует определенным правилам:
- Создайте таблицу
Products
со столбцомProductID
в качестве первичного ключа - Создайте таблицу
ProductRelations
со столбцомProductID
и столбцомRelatedID
и пометьте оба столбца как первичный ключ (составной ключ) - Не добавляйте другой столбец в таблицу
ProductRelations
. Два ключевых столбца должны быть единственными столбцами в таблице, чтобы позволить EF распознавать эту таблицу как таблицу ссылок для отношения "многие-ко-многим". - Создайте две отношения внешнего ключа между двумя таблицами:
- Первое отношение имеет таблицу
Products
как таблицу первичного ключа сProductID
как первичный ключ, а таблицуProductRelations
- как таблицу внешнего ключа с толькоProductID
как внешний ключ - Второе соотношение также имеет таблицу
Products
в качестве первичной таблицы ключей сProductID
в качестве первичного ключа, а таблицуProductRelations
- как таблицу внешнего ключа с толькоRelatedID
как иностранную ключ
- Первое отношение имеет таблицу
- Включить каскадное удаление для первого из двух отношений. (Вы не можете сделать это для обоих. SQL Server не позволит этого, потому что это приведет к нескольким каскадным путям удаления.)
Если вы создадите модель данных сущности из этих двух таблиц, теперь вы получите только один объект, а именно объект Product
(или, возможно, Products
, если вы отключите сингулярность). Таблица ссылок ProductRelations
не будет отображаться как объект.
Объект Product
будет иметь два свойства навигации:
public EntityCollection<Product> Products { get { ... } set { ... } }
public EntityCollection<Product> Products1 { get { ... } set { ... } }
Эти навигационные коллекции являются двумя конечными точками одного и того же отношения "многие ко многим" . (Если у вас было две разные таблицы, которые вы хотели связать по принципу "многие ко многим" , скажем, таблица A
и B
, одна коллекция навигации (Bs
) будет находиться в сущности A
, а другая (As
) будет в объекте B
. Но поскольку ваши отношения являются "саморегуляционными", оба свойства навигации находятся в объекте Product
.)
Смысл двух свойств: Products
являются продуктами, связанными с данным продуктом, Products1
являются продуктами, которые относятся к данному произведению. Например: Если это означает, что продукт нуждается в других продуктах в качестве деталей, которые должны быть изготовлены, и у вас есть продукты "Ноутбук", "Процессор", "Кремниевые чипы", тогда "Процессор" выполнен из "Silicon chips" ( "Silicon chips" - это элемент в коллекции Products
продукта продукта Processor
) и используется a "Блокнот" ( "Блокнот" - это элемент в Products1
совокупность объекта продукта Processor
). Вместо Products
и Products1
имена MadeOf
и UsedBy
были бы более подходящими.
Вы можете безопасно удалить одну из коллекций из сгенерированной модели, если вас интересует только одна сторона отношения. Просто удалите, например, Products1
на поверхности модели дизайнера. Вы также можете переименовать свойства. Связь будет по-прежнему много-ко-многим.
Edit
Как указано в комментарии, модель и сопоставление с использованием Code-First:
Модель:
public class Product
{
public int ProductID { get; set; }
public ICollection<Product> RelatedProducts { get; set; }
}
Mapping:
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.HasMany(p => RelatedProducts)
.WithMany()
.Map(m =>
{
m.MapLeftKey("ProductID");
m.MapRightKey("RelatedID");
m.ToTable("product_related");
});
}
}