C# 如何在EF Core 5中将主键移动到基表上 公共接口的可扩展性 { TId Id{get;set;} } 可审核的公共抽象类 { public int CreatedBy{get;set;} 公共用户CreatedUser{get;set;}=null!; 已创建公共日期时间{get;set;} 公共int LastModifiedBy{get;set;} 公共用户ModifiedUser{get;set;}=null!; 公共日期时间?LastModified{get;set;} } 公共类AccountStatus:可审核,可注册 { 公共int Id{get;set;} 公共字符串名称{get;set;}=null!; 公共字符串?代码{get;set;} 公共字符串?说明{get;set;} } 公共类AccountType:可审核、可扩展 { 公共长Id{get;set;}。。。 }
我正在为现有实现添加可审核的基本实体。当我从AuditTable实体继承时,我收到错误消息 无法在“AccountStatus”上配置密钥,因为它是派生类型。必须在根类型“Auditable”上配置密钥。如果您不希望“Auditable”包含在模型中,请确保它未被上下文中的DbSet属性引用、未在对ModelBuilder的配置调用中引用或未从模型中包含的类型的导航中引用 对于其他实体,键可以是int/long 我无法将键(Id)移动到基类,因为其他实体的键可能是int/long。如何在EF Core 5中实现这一点? 编辑:C# 如何在EF Core 5中将主键移动到基表上 公共接口的可扩展性 { TId Id{get;set;} } 可审核的公共抽象类 { public int CreatedBy{get;set;} 公共用户CreatedUser{get;set;}=null!; 已创建公共日期时间{get;set;} 公共int LastModifiedBy{get;set;} 公共用户ModifiedUser{get;set;}=null!; 公共日期时间?LastModified{get;set;} } 公共类AccountStatus:可审核,可注册 { 公共int Id{get;set;} 公共字符串名称{get;set;}=null!; 公共字符串?代码{get;set;} 公共字符串?说明{get;set;} } 公共类AccountType:可审核、可扩展 { 公共长Id{get;set;}。。。 },c#,asp.net-core,entity-framework-core,C#,Asp.net Core,Entity Framework Core,我正在为现有实现添加可审核的基本实体。当我从AuditTable实体继承时,我收到错误消息 无法在“AccountStatus”上配置密钥,因为它是派生类型。必须在根类型“Auditable”上配置密钥。如果您不希望“Auditable”包含在模型中,请确保它未被上下文中的DbSet属性引用、未在对ModelBuilder的配置调用中引用或未从模型中包含的类型的导航中引用 对于其他实体,键可以是int/long 我无法将键(Id)移动到基类,因为其他实体的键可能是int/long。如何在EF C
公共类AuditableMap:IEntityTypeConfiguration
{
公共void配置(EntityTypeBuilder)
{
属性(t=>t.Created).HasColumnType(“没有时区的时间戳”);
属性(t=>t.LastModified).HasColumnType(“没有时区的时间戳”);
HasOne(t=>t.CreatedUser).WithMany().HasForeignKey(t=>t.CreatedBy).OnDelete(DeleteBehavior.Restrict);
HasOne(t=>t.ModifiedUser).WithMany().HasForeignKey(t=>t.LastModifiedBy).OnDelete(DeleteBehavior.Restrict);
}
}
公共类AccountStatusMap:IEntityTypeConfiguration
{
公共void配置(EntityTypeBuilder)
{
builder.ToTable(“账户状态”,模式:“公共”);
HasKey(t=>t.Id);
builder.Property(t=>t.Name).HasMaxLength(100);
builder.Property(t=>t.Code).HasMaxLength(10);
builder.Property(t=>t.Description).HasMaxLength(200);
}
}
如果可审核的没有逻辑,但只是一个简单的数据类,则可以将其更改为接口:
public class AuditableMap : IEntityTypeConfiguration<Auditable>
{
public void Configure(EntityTypeBuilder<Auditable> builder)
{
builder.Property(t => t.Created).HasColumnType("timestamp without time zone");
builder.Property(t => t.LastModified).HasColumnType("timestamp without time zone");
builder.HasOne(t => t.CreatedUser).WithMany().HasForeignKey(t => t.CreatedBy).OnDelete(DeleteBehavior.Restrict);
builder.HasOne(t => t.ModifiedUser).WithMany().HasForeignKey(t => t.LastModifiedBy).OnDelete(DeleteBehavior.Restrict);
}
}
public class AccountStatusMap : IEntityTypeConfiguration<AccountStatus>
{
public void Configure(EntityTypeBuilder<AccountStatus> builder)
{
builder.ToTable("account_status", schema: "public");
builder.HasKey(t =>t.Id);
builder.Property(t =>t.Name).HasMaxLength(100);
builder.Property(t => t.Code).HasMaxLength(10);
builder.Property(t =>t.Description).HasMaxLength(200);
}
}
甚至可以考虑泛型基类,泛型定义了ID类型。但我不确定这是否适用于EF
PS:我怀疑AccountType是否需要一个长Id。请检查如果可审核的
没有逻辑,但只是一个简单的数据类,您可以将其更改为一个接口:
public class AuditableMap : IEntityTypeConfiguration<Auditable>
{
public void Configure(EntityTypeBuilder<Auditable> builder)
{
builder.Property(t => t.Created).HasColumnType("timestamp without time zone");
builder.Property(t => t.LastModified).HasColumnType("timestamp without time zone");
builder.HasOne(t => t.CreatedUser).WithMany().HasForeignKey(t => t.CreatedBy).OnDelete(DeleteBehavior.Restrict);
builder.HasOne(t => t.ModifiedUser).WithMany().HasForeignKey(t => t.LastModifiedBy).OnDelete(DeleteBehavior.Restrict);
}
}
public class AccountStatusMap : IEntityTypeConfiguration<AccountStatus>
{
public void Configure(EntityTypeBuilder<AccountStatus> builder)
{
builder.ToTable("account_status", schema: "public");
builder.HasKey(t =>t.Id);
builder.Property(t =>t.Name).HasMaxLength(100);
builder.Property(t => t.Code).HasMaxLength(10);
builder.Property(t =>t.Description).HasMaxLength(200);
}
}
甚至可以考虑泛型基类,泛型定义了ID类型。但我不确定这是否适用于EF
PS:我怀疑AccountType需要一个长Id。请检查不是直接的答案,但您可以使用组合而不是继承:将Audittable更改为接口并从中派生。那么这个问题就应该解决了。如果Auditable是一个没有任何逻辑的DTO,这应该不会是一个问题。您可以为相同的/提供示例代码。请注意错误消息:“如果您不希望模型中包含“Auditable”,请确保上下文中的DbSet属性未引用它、在对ModelBuilder的配置调用中未引用它或在模型中包含的类型的导航中未引用它。“你的模型/配置中的一些东西是让EF核心把代码> AuditableEntity <代码>作为实体,而不是一个基类,因为它似乎是意图。您必须自己查找并更正,或者发布您的model fluent配置,以便告诉您问题出在哪里以及如何更正。@IvanStoev我已经更新了qtn..thanksIt's,因为您有IEntityTypeConfiguration。您可能也喜欢。这不是一个直接的答案,但您可以使用组合而不是继承:将Audittable更改为接口并从中派生。那么这个问题就应该解决了。如果Auditable是一个没有任何逻辑的DTO,这应该不会是一个问题。您可以为相同的/提供示例代码。请注意错误消息:“如果您不希望模型中包含“Auditable”,请确保上下文中的DbSet属性未引用它、在对ModelBuilder的配置调用中未引用它或在模型中包含的类型的导航中未引用它。“你的模型/配置中的一些东西是让EF核心把代码> AuditableEntity <代码>作为实体,而不是一个基类,因为它似乎是意图。您必须自己查找并更正,或者发布您的model fluent配置,以便告诉您问题出在哪里以及如何更正。@IvanStoev我已经更新了qtn..thanksIt's,因为您有IEntityTypeConfiguration。你也可以喜欢。
public interface IAuditable
{
int CreatedBy { get; set; }
User CreatedUser { get; set; }; //I removed the null! here if need be, you might consider using Nullable-Types
DateTime Created { get; set; }
int LastModifiedBy { get; set; }
User ModifiedUser { get; set; };
DateTime? LastModified { get; set; }
}
public class AccountStatus : IAuditable, IEntity<int>
{
public int Id { get; set; }
public string Name { get; set; } = null!;
public string? Code { get; set; }
public string? Description { get; set; }
public int CreatedBy { get; set; }
public User CreatedUser { get; set; } = null!;
public DateTime Created { get; set; }
public int LastModifiedBy { get; set; }
public User ModifiedUser { get; set; } = null!;
public DateTime? LastModified { get; set; }
}
public class AccountType : IAuditable, IEntity<long>
{
public long Id { get; set; } ...
//add all fields from the interface IAuditable here as well
}
public class AuditableIdInt: IAuditable
{
public int Id { get; set; }
// all fields from the Interface
}
public class AuditableIdLong: IAuditable
{
public long Id { get; set; }
// all fields from the Interface
}