【Entity Framework】创建并配置模型

简介: 【Entity Framework】创建并配置模型

一、概述

EF Core使用元数据模型来描述如何将应用程序的实体类型映射到基础数据库。此模型是使用一组约定构建的,这些约定是寻找常用模式的启发式方法。然后,可以使用映射特性自定义模型和在OnModelCreating中调用ModelBuilder方法(也称为Fluent API),这两者都将替代约定执行的配置。

大多数配置可以应用于面向任何数据存储的模型。提供程序还可以启用特定于特定数据存储的配置,也可以忽略不支持或不适合的配置。

二、使用fluent API配置模型

可在派生上下文中替代OnModelCreating方法,并使用Fluent API类配置模型。此配置方法最为有效,并可在不修改实体类的情况下指定配置。此配置方法最为有效,并可在不修改实体类的情况下指定配置。Fluent API配置具有最高优先级,并将替代约定和数据注释。配置按调用方法的顺序应用,如果存在任何冲突,最新调用将替代以前指定的配置。

using Microsoft.EntityFrameworkCore;
namespace EFModeling.EntityProperties.FluentAPI.Required;
internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    #region Required
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property(b => b.Url)
            .IsRequired();
    }
    #endregion
}
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

三、分组配置

为了减少OnModelCreating方法的大小,可以将实体类型的所有配置提取到实现IEntityTypeConfiguration的单独类中。

public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
    public void Configure(EntityTypeBuilder<Blog> builder)
    {
        builder
            .Property(b => b.Url)
            .IsRequired();
    }
}

然后,只需从 OnModelCreating 调用 Configure 方法

new BlogEntityTypeConfiguration().Configure(modelBuilder.Entity<Blog>());

四、对实体类型使用EntityTypeConfigurationAttribute

与其显示调用Configure,不如改为在实体类型上放置EntityTypeConfigurationAttribute,以便EF Core可以查找并使用适当的配置。

[EntityTypeConfiguration(typeof(BookConfiguration))]
public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Isbn { get; set; }
}

此特性意味着,每方模型中包含Book实体类型时,EF Core都将使用指定的IEntityTypeConfiguration实现。实体类型包含在使用普通机制其中一种机制的模型中,例如,通过为实体类型创建DbSet属性:

public class BooksContext : DbContext
{
    public DbSet<Book> Books { get; set; }
}

或者将其注册到OnModelCreating:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Book>();
}

四、使用数据注释来配置模型

可以将某些特性(称为数据注释)应用于类和属性。数据注释替代约定,但会被Fluent API配置替代。

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;

namespace EFModeling.EntityProperties.DataAnnotations.Annotations;

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

[Table("Blogs")]
public class Blog
{
    public int BlogId { get; set; }

    [Required]
    public string Url { get; set; }
}

五、实体类型

在上下文中包含一种类型的DbSet意味着它包含在EF Core的模型中;我们通常将此类类型称为实体。EF Core可以从数据库中读取和写入实体实例,如果使用的是关系数据库,EF Core可以通过迁移为实例创建表。

5.1 在模型中包含类型

按照约定,上下文的DbSet属性中公开的类型作为实体包含在模型中。还包括在OnModelCreating方法中指定的实体类型,以及通过递归探索其他发现的实体类型的导航属性找到的任何类型。

下面的代码示例中包含了所有类型:

  • 包含 Blog,因为它在上下文的 DbSet 属性中公开。
  • 包含 Post,因为它是通过 Blog.Posts 导航属性发现的。
  • 包含 AuditEntry因为它是 OnModelCreating 中指定的。
internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<AuditEntry>();
    }
}
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; }
}
public class AuditEntry
{
    public int AuditEntryId { get; set; }
    public string Username { get; set; }
    public string Action { get; set; }
}

5.2 从模型中排除类型

如果不希望在模型中包含某一类型,可以使用NotMapped特性

[NotMapped]
public class BlogMetadata
{
    public DateTime LoadedFromDatabase { get; set; }
}

下面代码演示从Fluent API排除

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Ignore<BlogMetadata>();
}

5.3 从迁移中排除

将相同的实体类型映射到多个DbContext类型中,非常有用。在使用绑定上下文时,尤其如此,对于每段绑定上下文,使用不同DbContext类型的情况很常见。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<IdentityUser>()
        .ToTable("AspNetUsers", t => t.ExcludeFromMigrations());
}

此配置迁移不会创建AspNetUsers该表,但IdentityUser扔包含在模型中,并且可正常使用。

如果需要再次使用迁移来管理表,则应创建不包括AspNetUsers的新迁移。下一次迁移将包含对表所做的任何更改。

六、表名称与表架构

按照约定,每个实体类型都将设置为映射到公开实体的DbSet属性名称相同的数据库表,如果给定实体不存在DbSet,则使用类名称。

可以手动配置表名:

[Table("blogs")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Fluent API

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable("blogs");
}

使用关系数据库时,表按约定在数据库的默认架构中创建

[Table("blogs", Schema = "blogging")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Fluent API

[Table("blogs", Schema = "blogging")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}
[T
目录
相关文章
|
XML 存储 数据库连接
Entity Framework学习笔记——edmx文件
上文简单介绍了一下Entity FrameWork,这里说一下EF的核心——edmx文件。 在VisualStudio中建立edmx文件(此例环境为VisualStudio2012)
Entity Framework学习笔记——edmx文件
|
存储 开发框架 .NET
Entity Framework基础01
Entity Framework基础01
209 0
Entity Framework基础01
|
数据库 C#
Entity Framework 简单属性映射
Entity Framework 简单属性映射
1099 0
Entity Framework 简单属性映射
|
SQL 开发框架 Oracle
Entity Framework简介
Entity Framework简介
204 0
|
存储 开发框架 数据可视化
Entity Framework Core 简介
Entity Framework Core 简介
221 0
|
数据库
Entity Framework 迁移
Entity Framework 迁移
127 0
|
SQL 数据库
Entity Framework 小知识(二)
Entity Framework 小知识(二)
186 0
|
数据库 数据库管理
Entity Framework 小知识(一)
Entity Framework 小知识(一)
141 0