как сначала определить отношения «многие ко многим» и «один ко многим» между двумя объектами в коде?

Я создаю веб-сайт, используя код Entity Framework, где: пользователь может продавать много продуктов: один ко многим. пользователь может покупать много продуктов, а продукты могут покупать многие пользователи: многие ко многим. я продолжаю получать ошибку:

System.Data.SqlClient.SqlException: «Введение ограничения FOREIGN KEY «FK_dbo.UserProducts_dbo.Products_Product_ProductId» в таблице «UserProducts» может вызвать циклы или несколько каскадных путей. Укажите ON DELETE NO ACTION или ON UPDATE NO ACTION или измените другие ограничения FOREIGN KEY.

я хочу, чтобы каскадное удаление удаляло продукты, принадлежащие пользователю, который удалил свою учетную запись, или удалял записи из таблицы UserProduct, принадлежащие удаленному пользователю или удаленному продукту. Что я делаю неправильно?

это класс пользователя:

public class User
{
    public int UserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
    public string Email { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }


    public ICollection<Product> Products { get; set; }
    [InverseProperty("Users")]
    public ICollection<Product> Cart { get; set; }

    public User()
    {
        Products = new List<Product>();
        Cart = new List<Product>();
    }
}

это класс продукта:

public class Product
{
    [Key]
    public int ProductId { get; set; }
    public int OwnerId { get; set; }
    public string Title { get; set; }
    public string ShortDescription { get; set; }
    public string LongDescription { get; set; }

    public byte[] Picture1 { get; set; }
    public byte[] Picture2 { get; set; }
    public byte[] Picture3 { get; set; }

    [ForeignKey("OwnerId")]
    public User User { get; set; }
    public ICollection<User> Users { get; set; }

    public Product()
    {
        Users = new List<User>();
    }
}

person Itay Tur    schedule 06.04.2018    source источник
comment
nvm я говорю, но название ошеломило меня на мгновение, лол   -  person Christopher H.    schedule 06.04.2018
comment
Вы добавили ссылку на внешний ключ в построитель моделей?   -  person j9070749    schedule 06.04.2018
comment
@ j9070749 j9070749 добавить к чему? коллекции: ef framework делает это по соглашению, когда 2 сущности имеют коллекцию друг друга. а для «один ко многим» я использовал аннотацию внешнего ключа в модели продукта, которая должна выполнять эту работу.   -  person Itay Tur    schedule 06.04.2018
comment
Исключение четко говорит вам, что происходит. Вы должны выбрать один внешний ключ, способный к каскадному удалению. Используйте плавные сопоставления, чтобы отключить каскадное удаление на других FK.   -  person Gert Arnold    schedule 06.04.2018
comment
Исключение, сообщающее о наличии недопустимого ограничения между таблицей UserProducts и Product. но почему. если ef-framework создает таблицу UserProducts, принципами являются продукт и пользователь. удаление записи из UserProducts не должно влиять ни на таблицу продуктов, ни на таблицу пользователя. но удаление продукта или записи пользователя должно. где недопустимое каскадирование?. @GertArnold   -  person Itay Tur    schedule 07.04.2018
comment
@UNlessofficialchannel Когда вы удаляете User, UserProduct можно удалить через (1) User -> UserProduct или (2) User -> Product -> UserProduct, следовательно, несколько каскадных путей.   -  person Ivan Stoev    schedule 07.04.2018
comment
@IvanStoev вот как я хочу, чтобы это работало. Что сделать, чтобы эф принял его?   -  person Itay Tur    schedule 08.04.2018
comment
@UNlessofficialchannel Что вы хотите, это не всегда то, что вы можете получить. К сожалению, это ограничение EF (вытекающее из ограничения базы данных SqlServer), поэтому вы ничего не можете сделать, чтобы EF принял его. Все, что вы можете сделать, это подписаться на комментарий Герта Арнольда.   -  person Ivan Stoev    schedule 08.04.2018


Ответы (1)


сначала мне нужно было написать класс для средней таблицы в отношениях многие-ко-многим пользователи-продукты:

public class UserProduct
{
    [Key, Column(Order = 0), ForeignKey("User")]
    public int UserId { get; set; }
    [Key, Column(Order = 1), ForeignKey("Product")]
    public int ProductId { get; set; }

    public User User { get; set; }
    public Product Product { get; set; }
}

которые позволяют мне отключить каскад при удалении из этой таблицы в таблицу User (переопределяя OnModelCreating в классе контекста):

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Entity<UserProduct>().HasRequired(t => 
        t.User).WithMany(t => t.Cart).WillCascadeOnDelete(false);
    }

отключение каскада работает, потому что:

  1. это решает ошибку множественного каскадного пути.
  2. удаление пользователя по-прежнему приводит к удалению его продуктов и их пользовательских продуктов, а удаление продукта приводит к удалению его пользовательских продуктов.
person Itay Tur    schedule 08.04.2018