【问题标题】:EF Core base entity class inheritance and readonly propertiesEF Core 基实体类继承和只读属性
【发布时间】:2016-10-09 13:32:27
【问题描述】:

是否可以这样做:

public abstract class BaseEntity : IEntity
{
    private Guid _id;
    private DateTime _createdOn;
    private DateTime _modifiedOn;
    private byte[] _timestamp;

    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id => _id;

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public DateTime CreatedOn => _createdOn;

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime ModifiedOn => _modifiedOn;

    [Timestamp]
    public byte[] Timestamp => _timestamp;
}

这是基类,所有实体都应该继承自这个类。此外,此属性应该是只读的(我使用的是backing properties),因为 EF 需要处理它们。

public class Category : BaseEntity
{
    [Required]
    public string Name { get; set; }

    public string Description { get; set; }
}

OnModelCreating 是空的。 当我运行迁移时,我收到消息:

'实体类型'Project.Database.Models.Category'需要一个主要的 要定义的键。

【问题讨论】:

    标签: c# entity-framework asp.net-core entity-framework-core .net-core


    【解决方案1】:

    问题是您的 BaseEntity.Id 属性是只读的。

    您的 Id 属性实现为 expression-bodied member(=> 语法),它只是 get-only 属性的语法糖。

    所以,你的代码:

    public Guid Id => _id;
    

    相当于:

    public Guid Id { get { return _id; } }
    

    EF 必须能够设置映射属性的值。您必须使用传统语法来实现该属性,并且您必须提供一个 setter。如果您的上下文与您的模型在同一个程序集中,您可以将设置器标记为内部,以便该属性在程序集外部只读。如果您的上下文在不同的程序集中,您仍然可以将 setter 标记为内部,然后使用 InternalsVisibleTo 属性使内部对包含您的上下文的程序集可见。

    【讨论】:

    • 不应该使用支持字段来处理。那么应该在哪里使用支持字段呢?
    • 支持字段是 _id,在两种方法实现中都使用。但是,支持字段不是映射到数据库列的内容。该物业是。支持字段只是模型类中的一个私有机制,实体框架(以及其他一切)都不知道/不在乎。
    • 在创建对象时设置支持字段,属性是 EF 映射到数据库的内容。我仍然不明白为什么这不起作用。 “配置支持字段时,EF 将在从数据库实现实体实例时直接写入该字段(而不是使用属性设置器)。这在没有属性设置器或设置器包含不应该的逻辑时很有用在为从数据库加载的现有实体设置初始属性值时执行。" - 来自 ef 核心文档
    • 但是您的语法与将按照约定发现的支持字段的示例不匹配。您是否尝试过不使用表达式主体语法?您是否尝试过在上下文的 OnModelCreating 覆盖中使用 Fluent API .HasAnnotation("BackingField", "_id") 方法?
    【解决方案2】:

    这似乎是一个错误,因为如果您为 Id 属性提供 publicinternalprotected(但不是 private 或无)设置器,或者如果您指定密钥,则它可以工作派生实体显式通过 Fluent API

    modelBuilder.Entity<Category>().HasKey(e => e.Id);
    

    这当然违背了使用基类属性的全部目的。

    您可以考虑将其报告给 EF Core GitHub

    【讨论】:

    • 我不明白这是一个错误。正如您所指出的,如果该属性没有设置器,则它不起作用(并且无法工作)。在 OP 的代码中,该属性没有设置器。它不应该工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-04
    • 2022-01-25
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多