EF Core结合DDD实现数据库复合主键配置问题
EF Core配置DDD实体映射数据库复合主键方案
1. 定义DDD值对象ChecklistId
针对数据库的复合主键字段,设计不可变的值对象,保证值相等语义(推荐用record简化实现,也可手动实现IEquatable):
用Record实现(.NET 8推荐)
public record ChecklistId( int InspectionId, string QuestionGroup, string Question, string Answer);
用Class手动实现(如需自定义校验逻辑)
public class ChecklistId : IEquatable<ChecklistId> { public int InspectionId { get; } public string QuestionGroup { get; } public string Question { get; } public string Answer { get; } private ChecklistId(int inspectionId, string questionGroup, string question, string answer) { InspectionId = inspectionId; QuestionGroup = questionGroup ?? throw new ArgumentNullException(nameof(questionGroup)); Question = question ?? throw new ArgumentNullException(nameof(question)); Answer = answer ?? throw new ArgumentNullException(nameof(answer)); } public static ChecklistId Create(int inspectionId, string questionGroup, string question, string answer) { // 可添加业务校验:比如InspectionId不能为负,字符串非空等 return new ChecklistId(inspectionId, questionGroup, question, answer); } public bool Equals(ChecklistId other) { if (other is null) return false; return InspectionId == other.InspectionId && string.Equals(QuestionGroup, other.QuestionGroup, StringComparison.Ordinal) && string.Equals(Question, other.Question, StringComparison.Ordinal) && string.Equals(Answer, other.Answer, StringComparison.Ordinal); } public override bool Equals(object obj) => Equals(obj as ChecklistId); public override int GetHashCode() => HashCode.Combine(InspectionId, QuestionGroup, Question, Answer); }
2. 定义Checklist实体
实体以ChecklistId作为唯一标识,封装业务属性和行为:
public class Checklist { public ChecklistId Id { get; private set; } public DateTime CreatedAt { get; private set; } public string Inspector { get; private set; } // EF Core需要的无参构造(设为私有避免外部直接调用) private Checklist() { } // 业务构造函数,保证实体创建时的合法性 public Checklist(ChecklistId id, DateTime createdAt, string inspector) { Id = id ?? throw new ArgumentNullException(nameof(id)); CreatedAt = createdAt; Inspector = inspector ?? throw new ArgumentNullException(nameof(inspector)); } // 业务方法示例 public void UpdateInspector(string newInspector) { Inspector = newInspector ?? throw new ArgumentNullException(nameof(newInspector)); } }
3. EF Core Fluent API配置
在DbContext中通过Fluent API完成实体与数据库表的映射,重点是拆分值对象为复合主键列:
public class AppDbContext : DbContext { public DbSet<Checklist> Checklists { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("Your_Connection_String", opt => { // 适配SQL Server 2008的兼容级别 opt.UseCompatibilityLevel(100); // 可选:配置重试逻辑 opt.EnableRetryOnFailure(); }); } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Checklist>(entity => { // 将值对象的四个属性设为复合主键 entity.HasKey(c => new { c.Id.InspectionId, c.Id.QuestionGroup, c.Id.Question, c.Id.Answer }); // 映射值对象属性到数据库列(可指定列名、长度等) entity.Property(c => c.Id.InspectionId) .HasColumnName("InspectionId") .IsRequired(); entity.Property(c => c.Id.QuestionGroup) .HasColumnName("QuestionGroup") .HasMaxLength(100) .IsRequired(); entity.Property(c => c.Id.Question) .HasColumnName("Question") .HasMaxLength(200) .IsRequired(); entity.Property(c => c.Id.Answer) .HasColumnName("Answer") .HasMaxLength(500) .IsRequired(); // 映射其他业务属性 entity.Property(c => c.CreatedAt) .HasColumnName("CreatedAt") .IsRequired(); entity.Property(c => c.Inspector) .HasColumnName("Inspector") .HasMaxLength(50) .IsRequired(); // 指定数据库表名(若与实体名不一致) entity.ToTable("Checklist"); }); } }
4. 使用注意事项
- 查询实体:直接传入
ChecklistId实例即可,EF Core会自动解析为复合条件:
var targetId = ChecklistId.Create(1, "Safety", "Fire Extinguisher", "Pass"); var checklist = await dbContext.Checklists.FirstOrDefaultAsync(c => c.Id == targetId);
- 添加实体:通过业务构造函数创建合法实体后再入库:
var newChecklist = new Checklist( ChecklistId.Create(2, "Quality", "Material Check", "Conform"), DateTime.Now, "John Doe"); dbContext.Checklists.Add(newChecklist); await dbContext.SaveChangesAsync();
- SQL Server 2008兼容:避免使用2008不支持的特性(如JSON列、SEQUENCE),确保连接字符串适配旧版本Provider。
内容的提问来源于stack exchange,提问作者M.M
相关产品推荐
相关产品推荐

