冲扬心法

笑声激发自强,发愤、图强、飞身向上

   :: 首页  ::  ::  ::  :: 管理

阴影(Shadow property)和索引器(Indexer property)属性

  阴影属性,是指不在.net实体类中定义、但在EF核心模型中为该实体类型定义的属性。这些属性的值和状态纯粹在更改跟踪器中维护。当数据库中存在不应该在映射实体类型上公开的数据时,阴影属性非常有用。(相当于数据库表中的一些列,不需要在实体类中映射,但是可以在EF模型中定义、追踪、赋值等)

  索引器属性,是实体类型属性,由.net实体类的索引器支持。可以在类型实例上使用索引器对其进行访问。还允许向实体类型添加其他属性,而无需更改CLR类

 

  本节中,出现了一些和“关系”相关的概念,比如导航。关系,定义了两个实体类之间的关系(一对一、一对多、多对多),它对应着关系型数据库中的外键的概念。具体,可参考下一节内容。

1、外键阴影属性 Foreign key shadow properties

  阴影属性,最常用于外键属性,其中两个实体之间的关系由数据库中的外键值表示,但使用实体类型之间的导航属性在实体类型上管理关系。

  约定:当发现关系存在但是在依赖实体类中找不到外键属性时,EF就会引入一个阴影属性。

  该属性将被命名 <navigation property name><principal key property name> (用在依赖实体上的、且指向主实体的导航来命名);如果主体键属性名称包含导航属性的名称,则该名称将只是 <principal key property name> 。 如果依赖实体上没有导航属性,则会在其位置使用主体类型名称。示例中,将导致将BlogId阴影属性引入到Post实体中:

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 string BlogUrl { get; set; }
  // 由于没有CLR属性(上一行)保存此关系的外键,因此将创建一个影子属性。
   public Blog Blog { get; set; } }

 

2、配置阴影属性

  使用Fluent API配置阴影属性。示例,一旦您调用了Property的字符串重载方法,您就可以为其他属性链接任何配置调用;由于Blog没有名为LastUpdated的CLR属性,因此创建了一个阴影属性:

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; }
}

  如果提供给Property方法的参数名与现有属性(影子属性或实体类上定义的属性)的名称匹配,则代码将配置该现有属性,而不是引入新的影子属性。

3、访问阴影属性

  可以通过 API 获取和更改影子属性值 ChangeTracker :

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

  可以通过静态方法在 LINQ 查询中引用影子属性 EF.Property :

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

  在无跟踪查询后,不能访问阴影属性,因为更改跟踪器不跟踪返回的实体。

4、配置索引器属性

  您可以使用Fluent API来配置索引器属性。一旦调用了方法IndexerProperty,就可以为其他属性链接任何配置调用。在下面的示例中,在Blog类型的LastUpdated属性上定义了一个索引器,它将用于创建索引器属性:

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

  如果提供给方法的名称 IndexerProperty 与现有索引器属性的名称匹配,则代码将配置该现有属性。 如果实体类型具有由实体类的属性支持的属性,则会引发异常,因为索引器属性只能通过索引器访问。

5、属性包实体类型 Property bag entity types

  这是EF Core 5 的新特性。

  仅包含索引器属性的实体类型称为 "属性包实体类型"。 这些实体类型没有影子属性,而 EF 将创建索引器属性。 目前仅 Dictionary<string, object> 支持作为属性包实体类型。 它必须配置为具有唯一名称的共享实体类型,并且 DbSet 必须使用调用来实现相应的属性 Set :

class MyContext : DbContext
{
    public DbSet<Dictionary<string, object>> Blogs => Set<Dictionary<string, object>>("Blog");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.SharedTypeEntity<Dictionary<string, object>>("Blog", bb =>
        {
            bb.Property<int>("BlogId");
            bb.Property<string>("Url");
            bb.Property<DateTime>("LastUpdated");
        });
    }
}

 

posted on 2020-12-17 00:25  风雨一肩挑  阅读(378)  评论(0编辑  收藏  举报