实体框架多对多关系将数据留在连接表

时间:2017-04-27 18:23:16

标签: c# database entity-framework many-to-many

我尝试使用Entity Framework Code First进行多对多关系。

对象为CARDUSER_LIST; CARD可以为其分配多个USER_LIST,并且可以为多个USER_LIST分配一个CARD

这些类定义如下:

public partial class CARD : DBEntityItem {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]

        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int CARD_ID { get; set; }

        [StringLength(500)]
        public string SHORT_DESC { get; set; }

        public int STAGE_ID { get; set; }

        public int GROUP_ID { get; set; }

        public int FLAGS { get; set; }

        [StringLength(30)]
        public string OFFICE_APP_REF { get; set; }

        [StringLength(7)]
        public string CARD_COLOUR { get; set; }

        public int CTYPE_ID { get; set; }

        public virtual GROUP GROUP { get; set; }

        public virtual CARD_TYPE CARD_TYPE { get; set; }

        public virtual STAGE STAGE { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<USER_LIST> USER_LIST { get; set; }

        [NotMapped]
        public CardFlags FlagOptions { get; set; }

        public enum CardFlags {
            None = 0,
            Blocked = 1,
            Unexpected = 2,
            Emergency = 4,
            Failed = 8
        }

        public CARD()
            : base("CARD", "CARD_ID") {
            USER_LIST = new HashSet<USER_LIST>();
        }
    }

public partial class USER_LIST : DBEntityItem {
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int USER_ID { get; set; }

    [Required]
    [StringLength(100)]
    public string USER_NAME { get; set; }

    [Required]
    [StringLength(250)]
    public string PASSWORD { get; set; }

    [StringLength(250)]
    public string EMAIL { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<PREFERENCE_VALUE> PREFERENCE_VALUE { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<USER_PERMISSIONS> USER_PERMISSIONS { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<USER_TASK> USER_TASK { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<CARD> CARD { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<CHANGE_NOTE> CHANGE_NOTE { get; set; }

    public USER_LIST()
        : base("USER_LIST", "USER_ID") {
        PREFERENCE_VALUE = new HashSet<PREFERENCE_VALUE>();
        USER_PERMISSIONS = new HashSet<USER_PERMISSIONS>();
        USER_TASK = new HashSet<USER_TASK>();
        CARD = new HashSet<CARD>();
    }
}

忽略DBEntityItem和结果构造函数链的继承,因为它只是一个用于为实体提供一些附加功能的类。

多对多映射在OnModelCreating中定义如下:

modelBuilder.Entity<CARD>()
    .HasMany(e => e.USER_LIST)
    .WithMany(e => e.CARD)
    .Map(m => {
        m.MapLeftKey("CARD_ID");
        m.MapRightKey("USER_ID");
        m.ToTable("CARDUSER");
        });

这是因为'CARDUSER'是数据库中的现有表。

构建List<USER_LIST>并将其设置为针对USER_LIST对象的CARD属性。致电SaveChanges()时,会产生以下结果(如预期的那样):

MyCardObject.USER_LIST = MyListOfUsers;
MyDBContext.SaveChanges();

CARDUSER table data

可以看出,正确的条目已根据需要插入到CARDUSER表中。

当我尝试删除CARD时出现的问题:

MyDBContext.CARD.Remove(MyCardObject);
MyDBContext.SaveChanges();

以上将从CARD表中删除CARD记录;但是,CARDUSER中与此CARD相关的所有记录仍然存在:

There is nothing in the CARD table but CARDUSER still contains data

我遇到了以下问题,希望这会回答我的问题:

How delete many-to-many relation in Entity Framework 6

但是,我已经在DBContext中定义了“多对多”映射,而无需显式定义CARDUSER对象,因此我无法针对每个State对象设置CARDUSERDeleted

为什么这些数据在CARDUSER表中存在,以及如何设置它以便CARDUSER中的CARD_ID和USER_ID字段都是正确的,强制的外键值?我已经尝试在数据库本身的CARDUSER表上设置外键约束;但是,如果我这样做,那么当我针对USER_LIST对象设置CARD属性然后尝试保存更改时,会导致CARDUSER内的外键违规,系统尝试重新插入已针对CARD设置的所有条目。

2 个答案:

答案 0 :(得分:0)

在多对多关系中,您必须有一个交叉/桥牌表 你可以在你发布的链接中看到他有一个联结表。

答案 1 :(得分:0)

当您向连接表添加外键约束时,您处于正确的轨道上。 SQL Server(默认情况下)不会cascade通过外键关系删除,这就是您(正确地)收到错误的原因。如果将外键定义为on delete cascade,您将获得所需的行为。

或者,您可以在没有级联行为的情况下定义外键。如果这样做,您必须确保手动删除连接表中的条目。

相关问题