隐藏属性Shadow Properties

卷影属性是指你.NET 实体类中未定义但 EF Core模型中该实体类型定义。Shadow properties are properties that are not defined in your .NET entity class but are defined for that entity type in the EF Core model. 完全在更改跟踪器中维护的值和这些属性的状态。The value and state of these properties is maintained purely in the Change Tracker.

不应在映射的实体类型公开数据库中没有数据时,卷影属性非常有用。Shadow properties are useful when there is data in the database that should not be exposed on the mapped entity types. 它们通常用于外键属性,其中两个实体之间的关系表示通过在数据库中的外键值,但此关系管理使用实体类型之间的导航属性的实体类型上。They are most often used for foreign key properties, where the relationship between two entities is represented by a foreign key value in the database, but the relationship is managed on the entity types using navigation properties between the entity types.

阴影属性值可以获取并通过更改ChangeTrackerAPI。Shadow property values can be obtained and changed through the ChangeTracker API.

context.Entry(myBlog).Property("LastUpdated").CurrentValue = DateTime.Now;

可以通过 LINQ 查询中引用隐藏属性EF.Property静态方法。Shadow properties can be referenced in LINQ queries via the EF.Property static method.

var blogs = context.Blogs
    .OrderBy(b => EF.Property<DateTime>(b, "LastUpdated"));

约定Conventions

当发现一种关系,但依赖实体类中找到任何外键属性时,可以通过约定创建隐藏属性。Shadow properties can be created by convention when a relationship is discovered but no foreign key property is found in the dependent entity class. 在这种情况下,将引入了卷影的外键属性。In this case, a shadow foreign key property will be introduced. 卷影外键属性将被命名为<navigation property name><principal key property name>(指向主体实体,依赖实体的导航用于命名)。The shadow foreign key property will be named <navigation property name><principal key property name> (the navigation on the dependent entity, which points to the principal entity, is used for the naming). 如果主体键属性名称包含导航属性的名称,则名称只是将<principal key property name>If the principal key property name includes the name of the navigation property, then the name will just be <principal key property name>. 如果依赖实体上没有任何导航属性,则主体类型名称使用在其原位置。If there is no navigation property on the dependent entity, then the principal type name is used in its place.

例如,以下代码列表将导致BlogId影子属性引入到Post实体。For example, the following code listing will result in a BlogId shadow property being introduced to the Post entity.

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public Blog Blog { get; set; }
}

数据注释Data Annotations

使用数据注释,可以创建隐藏属性。Shadow properties can not be created with data annotations.

Fluent APIFluent API

可以使用 Fluent API 配置卷影属性。You can use the Fluent API to configure shadow properties. 一旦调用的字符串重载Property可以链接的任何其他属性会配置调用。Once you have called the string overload of Property you can chain any of the configuration calls you would for other properties.

如果名称提供给Property方法与现有属性 (的影子属性或一个实体类中定义) 的名称相匹配,则代码将配置该现有属性,而不是引入的新的影子属性。If the name supplied to the Property method matches the name of an existing property (a shadow property or one defined on the entity class), then the code will configure that existing property rather than introducing a new shadow property.

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property<DateTime>("LastUpdated");
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}