A.net core 2.0新特性支持通过IEntityTypeConfiguration<>添加Code First配置到一个封装类。

新建目标框架为.NET Core类库

新建完了以后右键点击程序集,选择属性,选择目标框架为.NET Core 2.0

在EntityFrameworkCore程序集中添加类User(用户)、Address(用户住址)、Book(书)、Author(作者)。这里不讨论各个类设计的合理性和程序架构,主要目的是为了演示各个类之间的关系配置。

User和Address类用于演示配置1-0..1关系。User和Book用于演示1-N,即1对多关系。Book和Author用于演示N-N关系,即多对多关系。

注意:在EF6.x中,当配置1-0..1关系时,附属表的主键值可以与主表的主键相同,主表对应这里的User,附属表对应Address,而由于篇幅有限,在.net core 2.0中不讨论此实现,即每个表都有自己的主键,表关联都通过外键作为实现。

User表实现如下

using System;

namespace EntityFrameworkCore
{
/// <summary>
/// 用户模型
/// </summary>
public sealed class User
{
public User()
{
ID = Guid.NewGuid();
TimeCreated = DateTime.Now;
} public Guid ID { get; private set; } /// <summary>
/// 用户名称
/// </summary>
public string Name { get; set; } /// <summary>
/// 用户登录密码
/// </summary>
public string Password { get; set; } /// <summary>
/// 用户创建时间
/// </summary>
public DateTime TimeCreated { get; private set; } public Address Address { get; set; } }
}

Address表实现如下

using System;

namespace EntityFrameworkCore
{
/// <summary>
/// 用户地址模型
/// </summary>
public sealed class Address
{
public Address()
{
ID = Guid.NewGuid();
TimeCreated = DateTime.Now;
}
public Guid ID { get; private set; } /// <summary>
/// 国家
/// </summary>
public string Country { get; set; } /// <summary>
/// 省
/// </summary>
public string Province { get; set; } /// <summary>
/// 城市
/// </summary>
public string City { get; set; } /// <summary>
/// 区/县
/// </summary>
public string Area { get; set; } /// <summary>
/// 街道
/// </summary>
public string Street { get; set; } /// <summary>
/// 创建时间
/// </summary>
public DateTime TimeCreated { get; private set; } /// <summary>
/// 用户ID
/// </summary>
public Guid UserID { get; set; } public User User { get; set; }
}
}

Book实现如下

using System;
using System.Collections.Generic; namespace EntityFrameworkCore
{
/// <summary>
/// 书模型
/// </summary>
public sealed class Book
{
public Book()
{
ID = Guid.NewGuid();
TimeCreated = DateTime.Now;
} public Guid ID { get; private set; }
public DateTime TimeCreated { get; private set; }
/// <summary>
/// 书名
/// </summary>
public string Name { get; set; } /// <summary>
/// 出版号
/// </summary>
public string PublicNo { get; set; } public List<Author> Authors { get; set; }
}
}

Author实现如下

using System;
using System.Collections.Generic; namespace EntityFrameworkCore
{
/// <summary>
/// 作者模型
/// </summary>
public sealed class Author
{
public Author()
{
ID = Guid.NewGuid();
TimeCreated = DateTime.Now;
} public Guid ID { get; private set; } public DateTime TimeCreated { get; private set; } /// <summary>
/// 作者名字
/// </summary>
public string Name { get; set; } public List<Book> Books { get; set; }
}
}

点击工具->NuGet包管理器->程序包管理控制台,在程序包管理控制台中输入命令:Install-Package Microsoft.EntityFrameworkCore.SqlServer

在EntityFrameworkCore中添加文件夹ModelConfigs


1-0..1关系配置User—Address:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace EntityFrameworkCore.ModelConfigs
{
public sealed class UserConfig:IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> builder)
{
builder.HasKey(q => q.ID);
builder.Property(q => q.Name).HasMaxLength().IsRequired();
builder.Property(q => q.Password).HasMaxLength().IsRequired();
builder.Property(q => q.TimeCreated).IsRequired(); //使用HasOne和WithOne两个扩展方法对User表和Address表进行1-1关系配置
builder.HasOne(q => q.Address).WithOne(q => q.User).HasForeignKey<Address>(q => q.UserID);
}
}
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace EntityFrameworkCore.ModelConfigs
{
public sealed class AddressConfig: IEntityTypeConfiguration<Address>
{
public void Configure(EntityTypeBuilder<Address> builder)
{
builder.HasKey(q => q.ID);
builder.Property(q => q.Area).HasMaxLength().IsRequired();
builder.Property(q => q.City).HasMaxLength().IsRequired();
builder.Property(q => q.Country).HasMaxLength().IsRequired();
builder.Property(q => q.Province).HasMaxLength().IsRequired();
builder.Property(q => q.Street).HasMaxLength().IsRequired();
builder.Property(q => q.TimeCreated).IsRequired();
builder.Property(q => q.UserID).IsRequired();
}
}
}

UserConfig和AddressConfig分别对User表数据和Address表数据进行了配置,添加FluentApiDemoDbContext类并继承DbContext,微软官方解释DbContext实例是一个带有数据库的会话并且能用于添加和查询实体。FluentApiDemoDbContext类代码如下:

using System;
using System.Linq;
using System.Reflection;
using Microsoft.EntityFrameworkCore; namespace EntityFrameworkCore
{
public class FluentApiDemoDbContext : DbContext
{
public FluentApiDemoDbContext(DbContextOptions<FluentApiDemoDbContext> options) : base(options)
{
} public DbSet<User> User { get; set; } public DbSet<Address> Address { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder); var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
.Where(q => q.GetInterface(typeof(IEntityTypeConfiguration<>).FullName) != null); foreach (var type in typesToRegister)
{ dynamic configurationInstance = Activator.CreateInstance(type);
modelBuilder.ApplyConfiguration(configurationInstance);
} }
}
}

如果这里直接把EntityFrameworkCore设为启动项,当在程序包管理控制台中输入:Update-Database时将报错:Unable to create an object of type 'FluentApiDemoDbContext'. Add an implementation of 'IDesignTimeDbContextFactory<FluentApiDemoDbContext>' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.提示需要添加一个IDesignTimeDbContextFactory<FluentApiDemoDbContext>的实现,这里如果是用Console写Demo,那么可以自行实现该接口,在该文中我将添加WebApi作为启用项。Startup.cs内容如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using EntityFrameworkCore; namespace WebApi
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var connection = @"Server=(localdb)\mssqllocaldb;Database=FluentApiDemoDb;Trusted_Connection=True;";
services.AddDbContextPool<FluentApiDemoDbContext>(options => options.UseSqlServer(connection));
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseMvc();
}
}
}

配置以后将该WebApi项目设置为启动项,在程序包管理控制台中输入:Add-Migration Initial以启动迁移。完成以后,项目会添加Migraions文件夹,

在程序包管理控制台中输入:Update-Database以完成数据迁移。完成后打开:视图->SQL Server对象资源管理器,可以查看比较具体的数据结构。

这里着重要看Address表中的UserID,UserID做为Address表的外键是非空的,按照文章开头说的1-0..1关系,这里只实现了1-1,并没有实现1-0关系,更改AddressConfig中的关系配置为:


builder.HasOne(q => q.User).WithOne(q => q.Address).HasForeignKey<Address>(q => q.UserID).IsRequired(false);

并更改Address中的代码为:


public Guid? UserID { get; set; }

添加迁移并更新到数据库


1-N关系配置,1个用户拥有多本书。在User表中添加

public List<Book> Books { get; set; }

Book表中添加

public Guid? UserID { get; set; }
public User User { get; set; }
 

在ModelConfigs中添加BookConfig

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace EntityFrameworkCore.ModelConfigs
{
public sealed class BookConfig: IEntityTypeConfiguration<Book>
{
public void Configure(EntityTypeBuilder<Book> builder)
{
builder.HasKey(q => q.ID);
builder.Property(q => q.Name).HasMaxLength().IsRequired();
builder.Property(q => q.PublicNo).HasMaxLength().IsRequired(); builder.HasOne(q => q.User).WithMany(q => q.Books).HasForeignKey(q => q.UserID).IsRequired(false);
}
}
}

在FluentApiDemoDbContext中注册实体

public DbSet<Book> Book { get; set; }

在程序包管理控制台中添加迁移并更新到数据库:


N-N关系配置,当使用EF6.x时,配置多对多关系,EF会自动生成中间表,在.net core中,需要手动添加关系表,实际上在EF6.x中当配置多对多关系时,也可以通过中间表配置1对多的方式实现多对多。

这里通过Book表和Author表实现多对多关系配置。一个作者可以有多本书,一本书有多个作者。

首先添加关系表AuthorsInBooks

using System;

namespace EntityFrameworkCore
{
public sealed class AuthorsInBooks
{
public Guid BookID { get; set; }
public Book Book { get; set; } public Guid AuthorID { get; set; } public Author Author { get; set; }
}
}

同时更改Books表

public List<Author> Authors { get; set; }

改为

public List<AuthorsInBooks> AuthorsInBooks { get; set; }

同理更改Author表

public List<Book> Books { get; set; }

改为

 public List<AuthorsInBooks> AuthorsInBooks { get; set; }

添加AuthorsConfig

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace EntityFrameworkCore.ModelConfigs
{
public sealed class AuthorConfig:IEntityTypeConfiguration<Author>
{
public void Configure(EntityTypeBuilder<Author> builder)
{
builder.HasKey(q => q.ID);
builder.Property(q => q.Name).HasMaxLength().IsRequired();
builder.Property(q => q.TimeCreated).IsRequired();
}
}
}

并在FluentApiDemoDbContext中注册Author

public DbSet<Author> Author { get; set; }

接下来添加AuthorsInBooksConfig

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace EntityFrameworkCore.ModelConfigs
{
public sealed class AuthorsInBooksConfig:IEntityTypeConfiguration<AuthorsInBooks>
{
public void Configure(EntityTypeBuilder<AuthorsInBooks> builder)
{
builder.HasKey(q => new
{
q.AuthorID,
q.BookID
}); builder.HasOne(q => q.Author).WithMany(q => q.AuthorsInBooks).HasForeignKey(q => q.AuthorID);
builder.HasOne(q => q.Book).WithMany(q => q.AuthorsInBooks).HasForeignKey(q => q.BookID);
}
}
}

在管理控制台中添加迁移并更新到数据库

.net core 2.0 Code First Fluent API配置的更多相关文章

  1. Entity Framework Code First (五)Fluent API - 配置关系

    上一篇文章我们讲解了如何用 Fluent API 来配置/映射属性和类型,本文将把重点放在其是如何配置关系的. 文中所使用代码如下 public class Student { public int ...

  2. Entity Framework Code First (五)Fluent API - 配置关系 转载 https://www.cnblogs.com/panchunting/p/entity-framework-code-first-fluent-api-configuring-relationships.html

    上一篇文章我们讲解了如何用 Fluent API 来配置/映射属性和类型,本文将把重点放在其是如何配置关系的. 文中所使用代码如下 public class Student { public int ...

  3. Entity Framework 实体框架的形成之旅--Code First模式中使用 Fluent API 配置(6)

    在前面的随笔<Entity Framework 实体框架的形成之旅--Code First的框架设计(5)>里介绍了基于Code First模式的实体框架的经验,这种方式自动处理出来的模式 ...

  4. Code First约定-Fluent API配置

    转自:http://blog.163.com/m13864039250_1/blog/static/2138652482015283397609/ 用Fluent API 配置/映射属性和类型 简介 ...

  5. EF CodeFirst方式 Fluent Api配置

    一.One-to-One Relationship[一对一关系] 两个表之间,只能由一个记录在另外一个表中.每一个主键的值,只能关联到另外一张表的一条或者零条记录.请记住,这个一对一的关系不是非常的普 ...

  6. 10.翻译系列:EF 6中的Fluent API配置【EF 6 Code-First系列】

    原文链接:https://www.entityframeworktutorial.net/code-first/fluent-api-in-code-first.aspx EF 6 Code-Firs ...

  7. EF里的默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射

    I.EF里的默认映射 上篇文章演示的通过定义实体类就可以自动生成数据库,并且EF自动设置了数据库的主键.外键以及表名和字段的类型等,这就是EF里的默认映射.具体分为: 数据库映射:Code First ...

  8. 使用 Fluent API 配置/映射属性和类型(摘自微软Data Access and Storage)

    使用 Fluent API 配置/映射属性和类型 使用实体框架 Code First 时,默认行为是使用一组 EF 中内嵌的约定将 POCO 类映射到表.但是,有时您无法或不想遵守这些约定,需要将实体 ...

  9. 使用Fluent API 配置/映射属性和类型

    Code First约定-Fluent API配置 使用Fluent API 配置/映射属性和类型 简介 通常通过重写派生DbContext 上的OnModelCreating 方法来访问Code F ...

随机推荐

  1. linux学习--2019-04-22

    1.写命令,vi编辑器 1)vi 文件名 2) 按 ‘i’ 进入编辑模式 3)编写完成后,按Esc,然后输入 “:wq” 推出编辑.(“q!”不存盘,强制退出vi) 2.命令补全 “Tab” 3.获取 ...

  2. Newtonsoft.Json输出Json时动态忽略属性

    一,前言 最近做项目采用Json形式和其他客户端交互,借助于Newtonsoft.Json . 由于业务场景不同,输出的Json内容也不同.要想忽略的属性,可以借助Newtonsoft.Json的特性 ...

  3. esb和eai的区别

    话说SOA也推了很多年了,出现了比如ESB.SCA.jbi等各类技术和标准,乱的很.各类比较也说的云里雾里,在下理一理,按自己的观点说说. 先说说esb和eai的区别. 个人观点:esb就是eai+设 ...

  4. $.each()和$().each(),以及forEach()的用法

    1.forEach() 是JS遍历数组的方法 var arr=[1,2,3]; arr.forEach(function(val,index,arr){ // var 为数组中当前的值 // inde ...

  5. centos 踩坑集锦

    定时任务 top 命令添加定时任务无效 我通过以下命令获取总进程数与僵尸进程数 vim procs.sh procs_total=`/bin/top -n 1|grep Tasks|sed 's/,/ ...

  6. codeforces_Codeforces Round #541 (Div. 2)_abc

    A. Sea Battle time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  7. ssh网上商城源码

    本人承诺源码免费,只是出于前期发布很多免费资源反而落不到好下场,总是被一些人说三道四.就算你去找到资源版本不符合你也运行不起来.如果想要资源加QQ1397617269,或者电话短信1395630164 ...

  8. Spring整合MybatisPlus学习笔记

    简介 MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发.提高效率而生 特性 无侵入:只做增强不做改变,引入它不会对现有 ...

  9. SSIS - 6.序列容器和优先约束

    一.多样的优先约束(看例子) 1)打开一个空白的SSIS包,拖拽4个脚本任务到设计面板上,重命名后连接起来,如下图所示. 2)执行包,可以看到任务执行成功.之后我们改变C和D之间的优先约束为“失败”. ...

  10. idea Empty git --version output:解决

    在使用idea下的git时候发现报错 但看了一下我的git-bas位置确实没有错啊,也可以启动 后来google了才下发现原来idea的这个地方不用引用的git-bash.exe的路径,而是git.e ...