EF Core 3.1中如何基于外键对象与日期列创建唯一约束
实体类代码
public class TenantUsageLog { [Key] public Guid Id { get; set; } public Tenant Tenant { get; set; } [DataType(DataType.Date)] public DateTime LogDate { get; set; } public int DatabaseRowCount { get; set; } public int DailyTraffic { get; set; } }
尝试的代码及错误
第一次尝试
代码:
builder.Entity<TenantUsageLog>().HasIndex(p => new { p.Tenant.Id, p.LogDate }).IsUnique();
错误信息:
The properties expression 'p => new <>f__AnonymousType5`2(Id = p.Tenant.Id, LogDate = p.LogDate)' is not valid. The expression should represent a simple property access: 't => t.MyProperty'. When specifying multiple properties use an anonymous type: 't => new { t.MyProperty1, t.MyProperty2 }'. (Parameter 'propertyAccessExpression')
第二次尝试
代码:
builder.Entity<TenantUsageLog>().HasIndex(p => new { p.Tenant, p.LogDate }).IsUnique();
错误信息:
The property 'TenantUsageLog.Tenant' is of type 'Tenant' which is not supported by current database provider. Either change the property CLR type or ignore the property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
解决方案
EF Core无法直接通过导航属性的子属性(p.Tenant.Id)创建索引,也不能直接将导航属性(Tenant)作为索引字段。正确做法是给实体添加显式外键属性,再基于外键和LogDate创建唯一索引。
步骤1:修改实体类,添加外键属性
在TenantUsageLog中添加对应Tenant的外键字段:
public class TenantUsageLog { [Key] public Guid Id { get; set; } // 显式外键属性,与Tenant实体的主键类型匹配 public Guid TenantId { get; set; } // 关联导航属性,指定外键 [ForeignKey(nameof(TenantId))] public Tenant Tenant { get; set; } [DataType(DataType.Date)] public DateTime LogDate { get; set; } public int DatabaseRowCount { get; set; } public int DailyTraffic { get; set; } }
步骤2:创建唯一索引
在OnModelCreating中使用外键属性和LogDate配置唯一索引:
builder.Entity<TenantUsageLog>() .HasIndex(p => new { p.TenantId, p.LogDate }) .IsUnique();
完成以上修改后,执行add-migration和update-database即可成功创建基于租户ID和日志日期的唯一约束,避免重复数据。
内容的提问来源于stack exchange,提问作者Tomas Shelby

