EF6+MySQL5.7自引用表关联属性为null问题排查求助
自引用表EF配置问题排查(MySQL 5.7.20 + EF6.0)
我最近在MySQL 5.7.20环境下用EF6.0实现自引用分类表,写了建表语句、实体类和模型配置,代码能正常运行,但查询_db.Categories时,哪怕加了Include子句,Parent属性和Children列表始终是null。想问问是我代码配置错了,还是这个功能只支持SQL Server?
先贴出我的代码:
1. MySQL建表语句
CREATE TABLE Category ( id int(11) PRIMARY KEY, name varchar(50), ParentId int(11) DEFAULT NULL, KEY `Parent_Key` (`ParentId`), CONSTRAINT `Parent_Key` FOREIGN KEY (`ParentId`) REFERENCES `Category` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION );
(注:原语句里Create table Category后缺少括号,我补上了,否则执行会报错)
2. EF实体代码
public class Category { public int Id {get; set;} public string Description {get; set;} public int? ParentId {get; set;} public virtual Category Parent {get; set;} public virtual ICollection<Category> Children {get; set;} };
3. EF模型配置代码
public class CategoryConfiguration : EntityTypeConfiguration<Category> { public CategoryConfiguration() { this.HasKey(e => new {e.id}) this.Property(e => e.id) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); this.HasOptional(e => e.Parent) .WithMany(e => Children) .HasForeignKey(e => new {e.id, e.ParentId); } }
问题出在哪?
别担心,自引用表在MySQL + EF6.0里完全支持,你的问题主要集中在实体映射错误和配置语法/逻辑错误上,具体来说:
1. 实体属性与数据库字段不匹配
你的实体里用了Description,但数据库表对应的字段是name,EF默认会按属性名匹配字段名,这就导致字段映射错误,进而影响整个实体的关系映射逻辑。要么把Description改成Name,要么在配置里明确映射:
this.Property(e => e.Description).HasColumnName("name");
2. 模型配置的多处错误
- 主键配置冗余且大小写不匹配:实体里的主键是
Id(大写),但配置里写的是e.id(小写),而且单个主键不需要用匿名类型,直接写HasKey(e => e.Id)就好。 WithMany参数错误:WithMany(e => Children)这里没有指定实体的Children属性,应该写成WithMany(e => e.Children),否则EF找不到关联的子集合。- 外键配置错误:外键只需要
ParentId,你却把id和ParentId一起作为外键,而且括号还没闭合,正确的写法是HasForeignKey(e => e.ParentId)。
3. 可选优化:初始化子集合
实体里的Children集合最好在构造函数里初始化,避免后续操作出现空引用异常:
public Category() { Children = new HashSet<Category>(); }
修正后的完整配置
把上述问题都修复后,配置应该是这样的:
public class CategoryConfiguration : EntityTypeConfiguration<Category> { public CategoryConfiguration() { // 映射表名(可选,但明确写出来更清晰) this.ToTable("Category"); // 主键配置 this.HasKey(e => e.Id); this.Property(e => e.Id) .HasColumnName("id") .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); // 映射Name字段(如果实体属性改成了Name) this.Property(e => e.Name) .HasColumnName("name") .HasMaxLength(50); // 自引用关系配置 this.HasOptional(e => e.Parent) .WithMany(e => e.Children) .HasForeignKey(e => e.ParentId) .HasConstraintName("Parent_Key") // 和数据库外键约束名对应 .WillCascadeOnDelete(false); // 对应ON DELETE NO ACTION } }
修正后再查询,不管是用Include(c => c.Parent)还是Include(c => c.Children),关联属性都能正常加载了。
内容的提问来源于stack exchange,提问作者viscroad
相关产品推荐
相关产品推荐

