繁体   English   中英

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

[英]Entity Framework Many to Many relationship leaves data in joining table

我尝试使用“实体框架代码优先”进行多对多关系。

对象是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的继承以及生成的构造函数链,因为这只是一个用于为Entities提供某些附加功能的类。

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> ,并将其设置为CARD对象的USER_LIST属性。 调用SaveChanges() ,这将导致以下结果(按预期):

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

CARDUSER表数据

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

当我尝试删除卡时出现了我遇到的问题:

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

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

CARD表中没有任何内容,但CARDUSER仍然包含数据

我遇到以下问题,并希望这能回答我的问题:

如何在Entity Framework 6中删除多对多关系

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

为什么此数据在CARDUSER表中徘徊,并且如何进行设置,以使CARDUSER中的CARD_ID和USER_ID字段都是正确的强制外键值? 我尝试在数据库本身内的CARDUSER表上设置外键约束; 但是,如果执行此操作,则当我对CARD对象设置USER_LIST属性,然后尝试保存USER_LIST的更改时,会导致CARDUSER违反外键,并且系统尝试重新插入所有已经对CARD设置了。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM