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# 如何在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

我正在为现有实现添加可审核的基本实体。当我从AuditTable实体继承时,我收到错误消息

无法在“AccountStatus”上配置密钥,因为它是派生类型。必须在根类型“Auditable”上配置密钥。如果您不希望“Auditable”包含在模型中,请确保它未被上下文中的DbSet属性引用、未在对ModelBuilder的配置调用中引用或未从模型中包含的类型的导航中引用

对于其他实体,键可以是int/long

我无法将键(Id)移动到基类,因为其他实体的键可能是int/long。如何在EF Core 5中实现这一点? 编辑:

公共类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
}