首页 > 编程语言 >c# 框架系列 ———— EFCore 模型篇 [一]

c# 框架系列 ———— EFCore 模型篇 [一]

时间:2022-09-05 00:12:02浏览次数:83  
标签:set 框架 get c# fluent api modelBuilder EFCore public

前言

简单介绍一下EfCore 的模型篇

正文

内容来源:

配置模型

配置模型的方式,一种是fluent api 还一种是属性的方式。

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

那么fluent api 怎么配置呢?

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

	protected override void OnModelCreating(ModelBuilder modelBuilder)
	{
		modelBuilder.Entity<Blog>()
			.Property(b => b.Url)
			.IsRequired();
	}
}

可以这么配置。

但是实际上项目中一般不会这么干。

理由也很简单,因为OnModelCreating 如果表很多的话,那么会非常臃肿,这样就不好维护了。

一般都是单独写一个配置:

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

然后:

这样每次加一个然后就要在OnModelCreating 增加配置就好。

然后官方还提供了一种方法:

modelBuilder.ApplyConfigurationsFromAssembly(typeof(BlogEntityTypeConfiguration).Assembly);

这种就是读取全部该程序集下面的实现IEntityTypeConfiguration的类,然后调用Configure。

然后官方也提示了。

应用配置的顺序是不确定的,因此仅当顺序不重要时才应使用此方法。

然后另外一种就是数据注释来配置模型:

这种数据注释的方式,没有fluent api的优先级高。

也就是说数据注释的,会被fluent api 覆盖。

这种和我们以前的方式一样哈。

那么这两种方式该如何选择呢?

其实这两种方式可以结合使用,然后fluent api 功能更强大,有些无法用数据注释来实现的,可以用fluent api。

如何包含到Ef Core 模型中呢?

有3中方式可以加入到EF Core 模型中。

第一种是:

public DbSet Blogs { get; set; }

第二种是作为导航属性默认加进去的:

前两种都是约定,第三种是调用方法:

在onModelCreating 中加入。

还有一种是希望模型中不包含某一种类型。

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

然后api 的方式这样用:

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

一般什么时候会用到呢? 一般是约定就包含了,但是自己又不希望包含。

比如前面导航属性,可能建立模型的就不将其加入实体中。

然后又一个从迁移中排除,倒是很好用的。

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

这个有什么用呢?

那就是相同的实体类型映射到多个DbContext 类型中使用。

这样会有一个问题,如果一个实体改变了,那么多个DbContext 的迁移都会为此作出动作。

那么这个时候就要保证只有一个DbContext 进行迁移。 理由也很简单,如果一个Dbcontext 进行了迁移,其他的Dbcontext 迁移就会报错了,因为这个时候数据库的表发生了变化。

然后表名称:

按照约定,每个实体类型都将设置为映射到与公开实体的 DbSet 属性名称相同的数据库表。 如果给定实体不存在 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 是下面这个:

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

使用关系数据库时,表按约定在数据库的默认架构中创建。 例如,Microsoft SQL Server 将使用 dbo 架构(SQLite 不支持架构)。

那么什么是表架构呢?

这个要从一段历史开始。

在sql server 2000的时候,访问数据库通过,数据库名.用户名.表名来访问。

而sql server 2005的时候,访问数据库是通过,数据库名.架构名.表名来访问的。

为什么做出这个改变呢? 那就是通过用户名来访问,不好管理权限。

后面引入架构名来对表进行逻辑分组,从而达到控制权限的目的。

比如一个数据库有多个架构,那么用户可以分配到对哪几个架构有什么权限,更加细节了。

而为什么我们一般访问的时候有一个dbo呢? 是因为我们默认使用的就是dbo。

那么为什么叫做dbo呢? 这个名字随便来的吗? 其实不是。

是这样的,在2000创建表的时候数据库名.用户名.表名来访问,这个时候默认用户名就是dbo。

这个时候2005的时候为了兼容这个东西,那么就使用了dbo作为默认架构了,大体就是这么回事。

表注释:

[Comment("Blogs managed on the website")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasComment("Blogs managed on the website");
}

前面说过fluent api 比我们的数据注释要更加强大,下面看几个数据注释无法搞定的。

比如视图映射:

modelBuilder.Entity<Blog>()
    .ToView("blogsView", schema: "blogging");

表值函数映射:

https://docs.microsoft.com/zh-cn/ef/core/modeling/entity-types?tabs=data-annotations#table-valued-function-mapping

然后fluent api 还至此共享类型实体类型,这个用的比较少。

https://docs.microsoft.com/zh-cn/ef/core/modeling/entity-types?tabs=fluent-api#shared-type-entity-types

下一节介绍乐观并发锁。

标签:set,框架,get,c#,fluent,api,modelBuilder,EFCore,public
From: https://www.cnblogs.com/aoximin/p/16588190.html

相关文章

  • Docker 部署
    部署docker1.关闭防火墙systemctlstopfirewalldsystemctldisablefirewalld2.停用并禁用selinux查看:getenforce临时禁用:setenforce0查看配置文件:grep^SELI......
  • 【JS每日一题】Array.reduce函数
    题目题目来源于前端面试题宝典[[0,1],[2,3]].reduce((acc,cur)=>{returnacc.concat(cur)},[1,2])解析[1,2]会作为初始值首次放入到第一个参数......
  • Docker 本地安装常用应用
    docker启动容器设置自启动加上配置:--restart=always比如:dockerrun-tid--name【定义容器名称】-p8081:8080--restart=always【镜像名称】如果是已经启动的容器......
  • springMVC 获取参数
    1.servlet@GetMapping("/params")publicStringtest5(HttpServletRequestrequest){Stringusername=request.getParameter("username");Stringpassword......
  • docker实战教程(一):安装
    centosdocker安装docker并非是一个通用的容器工具,它依赖于已存在的linux内核环境。docker实质上是在已运行的linux环境下制造了一个隔离的文件环境,因此它执行的效率几乎......
  • ECHART的使用方法
    项目中需要使用图表,最初使用的.NET自带的MSChart控件,做出来的效果不太好,所以又使用了Echarts控件。MSChart源码放在最后,可自行下载查看。Echarts是一个基于JavaScript......
  • 【Java可复用工具类-评论时间】传入LocalDateTime参数,返回一个时间【过去、昨天、今天
    1、效果2、代码importorg.springframework.stereotype.Component;importjava.time.Duration;importjava.time.LocalDate;importjava.time.LocalDateTime;impor......
  • Flask-SQLAlchemy无法连接SQL Server
    Flask-SQLAlchemy连接SQLServer时有可能会出现“未发现数据源名称并且未指定默认驱动程序”的异常,不能正确连接数据库,异常信息:sqlalchemy.exc.InterfaceError:(pyod......
  • F1C100S rt-smart 内核移植(二)
    前言本篇的内容进入了rt-smart内核的C语言世界,因此会同时涉及到较多的.c文件,需要读者对rt-smart内核有基本的认识,至少需要大致了解内核的文件结构。在上一章节中,我们从启......
  • windows系统命令行cmd查看显卡驱动版本号CUDA
    Win+R 输入cmd进入命令行输入nvidia-smi  ......