asp.net core系列 28 EF模型配置(字段,构造函数,拥有实体类型)

原文:asp.net core系列 28 EF模型配置(字段,构造函数,拥有实体类型)

一. 支持字段

EF允许读取或写入字段而不是一个属性。在使用实体类时,用面向对象的封装来限制或增强应用程序代码对数据访问的语义时,这可能很有用。无法使用数据注释配置。除了约定,还可以使用Fluent API为属性配置支持字段。

  1.1 约定

public class Blog
{
   // _<camel-cased property name>
    private string _url;

    public int BlogId { get; set; }

    public string Url
    {
        get { return _url; }
        set { _url = value; }
    }
}

  1.2 Fluent API

modelBuilder.Entity<Blog>()
            .Property(b => b.Url)
            .HasField("_validatedUrl");

public class Blog
{
    private string _validatedUrl;

    public string Url
    {
        get { return _validatedUrl; }
    }

    public void SetUrl(string url)
    {
       //...
        _validatedUrl = url;
    }
}

二. 构造函数

  从开始 EF Core 2.1,可以定义带参数的构造函数,并在创建实体实例时让EF Core调用此构造函数。构造函数参数可以绑定到映射属性,或绑定到各种服务,以方便延迟加载等行为。

  2.1  带参的构造函数

    下面代码演示带参数的构造函数,并且设置只读属性,外部调用该类时,只能通过构造函数传入实体值。

public class Blog
{
    public Blog(int id, string name, string author)
    {
        Id = id;
        Name = name;
        Author = author;
    }

    public int Id { get; private set; }

    public string Name { get; private set; }
    public string Author { get; private set; }

    public ICollection<Post> Posts { get; } = new List<Post>();
}

    别外使用私有setter的另一种方法是使属性真正只读,并在OnModelCreating中添加更明确的映射。

public class Blog
{
    private int _id;

    public Blog(string name, string author)
    {
        Name = name;
        Author = author;
    }

    public string Name { get; }
    public string Author { get; }

    public ICollection<Post> Posts { get; } = new List<Post>();
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>(
        b =>
        {
            b.HasKey("_id");
            b.Property(e => e.Author);
            b.Property(e => e.Name);
        });
}

  

  2.2 注入服务

    EF Core还可以将“服务”注入实体类型的构造函数中。例如,可以注入以下内容:

    DbContext - 当前上下文实例,也可以作为派生的DbContext类型键入

    ILazyLoader- 延迟加载服务

    Action<object, string>- 一个延迟加载的委托

     IEntityType - 与此实体类型关联的EF Core元数据

    例如,注入的DbContext可用于选择性地访问数据库以获得关于相关实体的信息而无需全部加载它们。在下面的示例中,这用于获取Blog博客中的Posts帖子数量:

public class Blog
{
    public Blog()
    {
    }

    private Blog(BloggingContext context)
    {
        Context = context;
    }

    private BloggingContext Context { get; set; }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Author { get; set; }

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

    //获取帖子数量
    public int PostsCount
        => Posts?.Count
           ?? Context?.Set<Post>().Count(p => Id == EF.Property<int?>(p, "BlogId"))
           ?? 0;
}

    有一些需要注意:

     (1)构造函数是私有的,因为它只由EF Core调用,并且还有另一个通用的公共构造函数。

      (2)使用注入服务的代码(即EF上下文)防御它为null,处理EF Core未创建实例的情况。

      (3)因为服务存储在读或写属性中,所以当实体附加到新的上下文实例时,它将被重置。

    2.2示例演示,没有成功,Blog带参的构造函数为私有,无法调用, context上下文总为null,以后在了解。

三.拥有的实体类型

  该功能是在 EF Core 2.0 中的新增功能。是指:当一个实体类中包含导航属性(实体类型引用属性),并对导航属性进行建模,这个导航属性类被称为“拥有实体类型”。而包含“拥有实体类型”的类叫:所有者。

  3.1 显示配置

    EF Core中的所有实体类型永远不会按照约定包含在模型中。可以使用OwnsOne在(使用EF Core 2.1中的新增功能)OnModelCreating中使用或用注释类型OwnedAttribute将类型配置为拥有类型。

    下面示例中StreetAddress是一个没有标识属性的类型。 它用作 Order 类型的属性来指定特定订单的发货地址。

//拥有实体类型
 [Owned]
public class StreetAddress
{
    public string Street { get; set; }
    public string City { get; set; }
}

//所有者
public class Order
{
    public int Id { get; set; }

    public StreetAddress ShippingAddress { get; set; }
}

public class BloggingContext : DbContext
{
    public BloggingContext(DbContextOptions<BloggingContext> options)
            : base(options)
        { }
    public DbSet<Order> Order { get; set; }}

    使用EF基于数据模型(Order)创建数据库,如下图所示。

        

    还可以使用该OwnsOne方法在OnModelCreating指定ShippingAddress属性,是Order实体类型的拥有实体,并根据需要配置其他方面。

    modelBuilder.Entity<Order>().OwnsOne(p => p.ShippingAddress);

    如果ShippingAddress属性在Order实体中为私有属性,则可以使用的字符串版本OwnsOne方法:

    modelBuilder.Entity<Order>().OwnsOne(typeof(StreetAddress), "ShippingAddress");

  3.2 隐含键

    OwnsOne通过引用导航配置或发现的拥有类型始终与所有者具有一对一的关系,因此拥有实体不需要自己的键值,因为外键值是唯一的。在前面的示例中,StreetAddress类型不需要定义键属性。拥有实体类型的实例键值与所有者实例的键值相同。

  3.3 拥有的集合类型

    要配置拥有的集合类型,使用OwnsManyOnModelCreating中使用。但是,主键不会按约定配置,因此需要明确指定。下面代码演示拥有的集合类型的关键代码。

    public class Distributor
    {
        public int Id { get; set; }
        public ICollection<StreetAddress> ShippingCenters { get; set; }
    }

   modelBuilder.Entity<Distributor>().OwnsMany(p => p.ShippingCenters, a =>
            {
                // 给ShippingCenters表设置一个主键
                a.Property<int>("Id");
                //给ShippingCenters表设置一个外键
                a.HasForeignKey("DistributorId");
                //设置复合主键
                a.HasKey("DistributorId", "Id");
            });

    使用EF基于数据模型(Distributor)创建数据库,如下图所示(一对多的关系)。Distributor_ShippingCenters表的ID为主键,DistributorId为外键。

    关于拥有的实体类型的更多介绍参考官方文档,这里不是介绍。关于“EF模型配置系列”的很多功能,都是基于code first模式。

  参考文献:

    官方文档:EF支持字段

           EF构造函数

           EF拥有的实体类型

           拥有实体类型的完整案例

原文地址:https://www.cnblogs.com/lonelyxmas/p/10409980.html

时间: 2024-10-25 22:10:24

asp.net core系列 28 EF模型配置(字段,构造函数,拥有实体类型)的相关文章

asp.net core系列 27 EF模型配置(索引,备用键,继承)

一.索引 索引是许多数据存储中的常见概念.虽然它们在数据存储中的实现可能会有所不同,但它们可用于更有效地基于列(或列集)进行查找.按照约定,用作外键每个属性 (或组的属性) 会自动创建索引.无法使用数据注释创建索引. 1.1 非唯一索引 Fluent API 在单个属性上指定索引.默认情况下,索引是非唯一的.如下代码示例在Blogs表上创建Url列索引: class MyContext : DbContext { public DbSet<Blog> Blogs { get; set; } p

asp.net core系列 30 EF管理数据库架构--必备知识 迁移

原文:asp.net core系列 30 EF管理数据库架构--必备知识 迁移 一.管理数据库架构概述 EF Core 提供两种主要方法来保持 EF Core 模型和数据库架构同步.一是以 EF Core 模型为基准,二是以数据库为基准. (1)如果希望以 EF Core 模型为准,请使用迁移. 对 EF Core 模型进行更改时,此方法会以增量方式将相应架构更改应用到数据库,以使数据库保持与 EF Core 模型兼容.  (2)如果希望以数据库架构为准,请使用反向工程. 使用此方法,可通过将数

asp.net core 系列 20 EF基于数据模型创建数据库

原文:asp.net core 系列 20 EF基于数据模型创建数据库 一.概述 本章使用 Entity Framework Core 构建执行基本数据访问的 ASP.NET Core MVC 应用程序.使用迁移(migrations)基于数据模型创建数据库,是一种code first模式.可以在Windows 上使用 Visual Studio 2017,或在 Windows.macOS 或 Linux 上使用 .NET Core CLI 来学习.已经安装了NET Core 2.1 SDK,这

asp.net core 系列 22 EF(连接字符串,连接复原,DbContext)

原文:asp.net core 系列 22 EF(连接字符串,连接复原,DbContext) 一.连接字符串 在上二篇中,ASP.NET Core 应用程序连接字符串是写死在ConfigureServices代码中,下面介绍通过配置来实现.连接字符串可以存储在 appsettings.json.用户机密存储.其他配置源中. 下面示例演示appsettings.json 中存储的连接字符串,这样不管asp.net core在什么环境(Development.Staging .Production)

asp.net core系列 32 EF查询数据 必备知识(1)

一.查询的工作原理 Entity Framework Core 使用语言集成查询 (LINQ) 来查询数据库中的数据. 通过 LINQ 可使用 C#(或你选择的其他 .NET 语言)基于派生上下文和实体类编写强类型查询. LINQ 查询的表示形式会传递给数据库提供程序,进而转换为特定的数据库查询语言(例如,适用于关系数据库的 SQL). 1.1 查询的生命周期, 下面是每个查询所经历的过程概述: (1) LINQ 查询由 E F处理,用于生成已准备好的表示形式,由数据库提供程序处理.缓存结果,以

asp.net core系列 35 EF保存数据(2) -- EF系列结束

一.事务 (1) 事务接着上篇继续讲完.如果使用了多种数据访问技术,来访问关系型数据库,则可能希望在这些不同技术所执行的操作之间共享事务.下面示例显示了如何在同一事务中执行 ADO.NET SqlClient 操作和 Entity Framework Core 操作. using (var connection = new SqlConnection(connectionString)) { //使用ado.net 打开数据库连接 connection.Open(); //使用ado.net 开

目录导航「深入浅出ASP.NET Core系列」

希望给你3-5分钟的碎片化学习,可能是坐地铁.等公交,积少成多,水滴石穿,谢谢关注. 入门篇 1.1课程介绍「深入浅出ASP.NET Core系列」 1.2环境安装「深入浅出ASP.NET Core系列」 1.3创建项目「深入浅出ASP.NET Core系列」 1.4部署到IIS「深入浅出ASP.NET Core系列」 1.5准备CentOS和Nginx环境「深入浅出ASP.NET Core系列」 1.6部署到CentOS「深入浅出ASP.NET Core系列」 2.1命令行和JSON的配置「深

asp.net core系列 48 Identity 身份模型自定义

原文:asp.net core系列 48 Identity 身份模型自定义 一.概述 ASP.NET Core Identity提供了一个框架,用于管理和存储在 ASP.NET Core 应用中的用户帐户. Identity添加到项目时单个用户帐户选择作为身份验证机制. 默认情况下,Identity可以使用的 Entity Framework (EF) Core 数据模型. 本文介绍如何自定义的身份标识模型. 1.1 下面是已经存在的身份模型, 由以下实体类型组成: 实体类型 说明 关系 Use

asp.net core系列 36 WebAPI 搭建详细示例

原文:asp.net core系列 36 WebAPI 搭建详细示例 一.概述 HTTP不仅仅用于提供网页.HTTP也是构建公开服务和数据的API强大平台.HTTP简单灵活且无处不在.几乎任何你能想到的平台都有一个HTTP库,因此HTTP服务可以覆盖广泛的客户端,包括浏览器,移动设备和传统的桌面应用程序. ASP.NET Web API 是一个框架,基于.NET Framework 或.NET Core 之上构建 Web API. 从本章开始学习Web API系列时,先从一个示例开始,下面使用A