【发布时间】:2017-04-27 18:23:16
【问题描述】:
我尝试了使用实体框架代码优先的多对多关系。
对象是CARD和USER_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> 已构建并设置为针对 CARD 对象的 USER_LIST 属性。调用SaveChanges() 时,结果如下(如预期):
MyCardObject.USER_LIST = MyListOfUsers;
MyDBContext.SaveChanges();
可以看出,正确的条目已按要求插入到 CARDUSER 表中。
我尝试删除卡时出现的问题:
MyDBContext.CARD.Remove(MyCardObject);
MyDBContext.SaveChanges();
以上将从 CARD 表中删除 CARD 记录;但是,CARDUSER 中与此 CARD 相关的所有记录仍然存在:
我遇到了以下问题,并希望这能回答我的问题:
How delete many-to-many relation in Entity Framework 6
但是,我已经在 DBContext 中定义了多对多映射,而无需显式定义 CARDUSER 对象,因此我无法将每个 CARDUSER 对象的 State 设置为 Deleted。
为什么这些数据在 CARDUSER 表中徘徊,如何设置它以使 CARDUSER 中的 CARD_ID 和 USER_ID 字段都是正确的强制外键值?我尝试在数据库本身的 CARDUSER 表上设置外键约束;但是,如果我这样做,那么当我针对CARD 对象设置USER_LIST 属性然后尝试保存更改时,它会导致CARDUSER 中的外键冲突,系统会尝试重新插入已针对 CARD 设置的所有条目。
【问题讨论】:
-
看起来你已经删除了
ManyToManyCascadeDeleteConvention。
标签: c# database entity-framework many-to-many