EF Core 6 新功能汇总(一)

在这篇文章中,你将看到 EF Core 6 中的十个新功能,包括新的特性标注,对时态表、稀疏列的支持,以及其他新功能。

1Unicode 特性

在 EF Core 6.0 中,新的 UnicodeAttribute 允许你将一个字符串属性映射到一个非 Unicode 列,而不需要直接指定数据库类型。当数据库系统只支持 Unicode 类型时,Unicode 特性会被忽略。

public class Book
{public int Id { get; set; }public string Title { get; set; }[Unicode(false)][MaxLength(22)]public string Isbn { get; set; }
}

对应的迁移代码:

protected override void Up(MigrationBuilder migrationBuilder)
{migrationBuilder.CreateTable(name: "Books",columns: table => new{Id = table.Column<int>(type: "int", nullable: false).Annotation("SqlServer:Identity", "1, 1"),Title = table.Column<string>(type: "nvarchar(max)", nullable: true),Isbn = table.Column<string>(type: "varchar(22)", unicode: false, maxLength: 22, nullable: true)},constraints: table =>{table.PrimaryKey("PK_Books", x => x.Id);});
}

2Precision 特性

在 EF Core 6.0 之前,你可以用 Fluent API 配置精度。现在,你也可以用数据标注和一个新的 PrecisionAttribute 来做这件事。

public class Product
{public int Id { get; set; }[Precision(precision: 10, scale: 2)]public decimal Price { get; set; }
}

对应的迁移代码:

protected override void Up(MigrationBuilder migrationBuilder)
{migrationBuilder.CreateTable(name: "Products",columns: table => new{Id = table.Column<int>(type: "int", nullable: false).Annotation("SqlServer:Identity", "1, 1"),Price = table.Column<decimal>(type: "decimal(10,2)", precision: 10, scale: 2, nullable: false)},constraints: table =>{table.PrimaryKey("PK_Products", x => x.Id);});
}

3EntityTypeConfiguration 特性

从 EF Core 6.0 开始,你可以在实体类型上放置一个新的 EntityTypeConfiguration 特性,这样 EF Core 就可以找到并使用适当的配置。在此之前,类的配置必须被实例化并从 OnModelCreating 方法中调用。

public class ProductConfiguration : IEntityTypeConfiguration<Product>
{public void Configure(EntityTypeBuilder<Product> builder){builder.Property(p => p.Name).HasMaxLength(250);builder.Property(p => p.Price).HasPrecision(10, 2);}
}
[EntityTypeConfiguration(typeof(ProductConfiguration))]
public class Product
{public int Id { get; set; }public decimal Price { get; set; }public string Name { get; set; }
}

4Column 特性

当你在模型中使用继承时,你可能不满意创建的表中默认的 EF Core 列顺序。在 EF Core 6.0 中,你可以用 ColumnAttribute 指定列的顺序。

此外,你还可以使用新的 Fluent API--HasColumnOrder() 来实现。

public class EntityBase
{[Column(Order = 1)]public int Id { get; set; }[Column(Order = 99)]public DateTime UpdatedOn { get; set; }[Column(Order = 98)]public DateTime CreatedOn { get; set; }
}
public class Person : EntityBase
{[Column(Order = 2)]public string FirstName { get; set; }[Column(Order = 3)]public string LastName { get; set; }public ContactInfo ContactInfo { get; set; }
}
public class Employee : Person
{[Column(Order = 4)]public string Position { get; set; }[Column(Order = 5)]public string Department { get; set; }
}
[Owned]
public class ContactInfo
{[Column(Order = 10)]public string Email { get; set; }[Column(Order = 11)]public string Phone { get; set; }
}

对应的迁移代码:

protected override void Up(MigrationBuilder migrationBuilder)
{migrationBuilder.CreateTable(name: "Employees",columns: table => new{Id = table.Column<int>(type: "int", nullable: false).Annotation("SqlServer:Identity", "1, 1"),FirstName = table.Column<string>(type: "nvarchar(max)", nullable: true),LastName = table.Column<string>(type: "nvarchar(max)", nullable: true),Position = table.Column<string>(type: "nvarchar(max)", nullable: true),Department = table.Column<string>(type: "nvarchar(max)", nullable: true),ContactInfo_Email = table.Column<string>(type: "nvarchar(max)", nullable: true),ContactInfo_Phone = table.Column<string>(type: "nvarchar(max)", nullable: true),CreatedOn = table.Column<DateTime>(type: "datetime2", nullable: false),UpdatedOn = table.Column<DateTime>(type: "datetime2", nullable: false)},constraints: table =>{table.PrimaryKey("PK_Employees", x => x.Id);});
}

5时态表

EF Core 6.0 支持 SQL Server 的时态表。一个表可以被配置成一个具有 SQL Server 默认的时间戳和历史表的时态表。

public class ExampleContext : DbContext
{public DbSet<Person> People { get; set; }protected override void OnModelCreating(ModelBuilder modelBuilder){modelBuilder.Entity<Person>().ToTable("People", b => b.IsTemporal());}protected override void OnConfiguring(DbContextOptionsBuilder options)=> options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=TemporalTables;Trusted_Connection=True;");
}
public class Person
{public int Id { get; set; }public string Name { get; set; }
}

对应的迁移代码:

protected override void Up(MigrationBuilder migrationBuilder)
{migrationBuilder.CreateTable(name: "People",columns: table => new{Id = table.Column<int>(type: "int", nullable: false).Annotation("SqlServer:Identity", "1, 1"),Name = table.Column<string>(type: "nvarchar(max)", nullable: true),PeriodEnd = table.Column<DateTime>(type: "datetime2", nullable: false).Annotation("SqlServer:IsTemporal", true).Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd").Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart"),PeriodStart = table.Column<DateTime>(type: "datetime2", nullable: false).Annotation("SqlServer:IsTemporal", true).Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd").Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart")},constraints: table =>{table.PrimaryKey("PK_People", x => x.Id);}).Annotation("SqlServer:IsTemporal", true).Annotation("SqlServer:TemporalHistoryTableName", "PersonHistory").Annotation("SqlServer:TemporalHistoryTableSchema", null).Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd").Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
}

你可以用以下方法查询和检索历史数据:

  • TemporalAsOf

  • TemporalAll

  • TemporalFromTo

  • TemporalBetween

  • TemporalContainedIn

使用时态表:

using ExampleContext context = new();
context.People.Add(new() { Name = "Oleg" });
context.People.Add(new() { Name = "Steve" });
context.People.Add(new() { Name = "John" });
await context.SaveChangesAsync();var people = await context.People.ToListAsync();
foreach (var person in people)
{var personEntry = context.Entry(person);var validFrom = personEntry.Property<DateTime>("PeriodStart").CurrentValue;var validTo = personEntry.Property<DateTime>("PeriodEnd").CurrentValue;Console.WriteLine($"Person {person.Name} valid from {validFrom} to {validTo}");
}
// Output:
// Person Oleg valid from 06-Nov-21 17:50:39 PM to 31-Dec-99 23:59:59 PM
// Person Steve valid from 06-Nov-21 17:50:39 PM to 31-Dec-99 23:59:59 PM
// Person John valid from 06-Nov-21 17:50:39 PM to 31-Dec-99 23:59:59 PM

查询历史数据:

var oleg = await context.People.FirstAsync(x => x.Name == "Oleg");
context.People.Remove(oleg);
await context.SaveChangesAsync();
var history = context.People.TemporalAll().Where(e => e.Name == "Oleg").OrderBy(e => EF.Property<DateTime>(e, "PeriodStart")).Select(p => new{Person = p,PeriodStart = EF.Property<DateTime>(p, "PeriodStart"),PeriodEnd = EF.Property<DateTime>(p, "PeriodEnd")}).ToList();
foreach (var pointInTime in history)
{Console.WriteLine($"Person {pointInTime.Person.Name} existed from {pointInTime.PeriodStart} to {pointInTime.PeriodEnd}");
}// Output:
// Person Oleg existed from 06-Nov-21 17:50:39 PM to 06-Nov-21 18:11:29 PM

检索历史数据:

var removedOleg = await context.People.TemporalAsOf(history.First().PeriodStart).SingleAsync(e => e.Name == "Oleg");Console.WriteLine($"Id = {removedOleg.Id}; Name = {removedOleg.Name}");
// Output:
// Id = 1; Name = Oleg

了解更多关于时态表的信息:

https://devblogs.microsoft.com/dotnet/prime-your-flux-capacitor-sql-server-temporal-tables-in-ef-core-6-0/

6稀疏列

EF Core 6.0 支持 SQL Server 稀疏列。在使用 TPH(table per hierarchy)继承映射时,它可能很有用。

public class ExampleContext : DbContext
{public DbSet<Person> People { get; set; }public DbSet<Employee> Employees { get; set; }public DbSet<User> Users { get; set; }protected override void OnModelCreating(ModelBuilder modelBuilder){modelBuilder.Entity<User>().Property(e => e.Login).IsSparse();modelBuilder.Entity<Employee>().Property(e => e.Position).IsSparse();}protected override void OnConfiguring(DbContextOptionsBuilder options)=> options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=SparseColumns;Trusted_Connection=True;");
}public class Person
{public int Id { get; set; }public string Name { get; set; }
}
public class User : Person
{public string Login { get; set; }
}
public class Employee : Person
{public string Position { get; set; }
}

对应迁移代码:

protected override void Up(MigrationBuilder migrationBuilder)
{migrationBuilder.CreateTable(name: "People",columns: table => new{Id = table.Column<int>(type: "int", nullable: false).Annotation("SqlServer:Identity", "1, 1"),Name = table.Column<string>(type: "nvarchar(max)", nullable: false),Discriminator = table.Column<string>(type: "nvarchar(max)", nullable: false),Position = table.Column<string>(type: "nvarchar(max)", nullable: true).Annotation("SqlServer:Sparse", true),Login = table.Column<string>(type: "nvarchar(max)", nullable: true).Annotation("SqlServer:Sparse", true)},constraints: table =>{table.PrimaryKey("PK_People", x => x.Id);});
}

稀疏列有限制,具体请看文档:

https://docs.microsoft.com/en-us/sql/relational-databases/tables/use-sparse-columns?view=sql-server-ver15

7EF Core 中的最小 API

EF Core 6.0 有它自己的最小 API。新的扩展方法可在同一行代码注册一个 DbContext 类型,并提供一个数据库 Provider 的配置。

const string AccountKey = "[CosmosKey]";var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSqlServer<MyDbContext>(@"Server = (localdb)\mssqllocaldb; Database = MyDatabase");// OR
builder.Services.AddSqlite<MyDbContext>("Data Source=mydatabase.db");// OR
builder.Services.AddCosmos<MyDbContext>($"AccountEndpoint=https://localhost:8081/;AccountKey={AccountKey}", "MyDatabase");var app = builder.Build();
app.Run();class MyDbContext : DbContext
{ }

8迁移包

在 EF Core 6.0 中,有一个新的有利于 DevOps 的功能--迁移包。它允许创建一个包含迁移的小型可执行程序。你可以在 CD 中使用它。不需要复制源代码或安装 .NET SDK(只有运行时)。

CLI:

dotnet ef migrations bundle --project MigrationBundles

Package Manager Console:

Bundle-Migration

49c55613ada33c4d99533877bd7bbd4d.png

更多介绍:

https://devblogs.microsoft.com/dotnet/introducing-devops-friendly-ef-core-migration-bundles/

9预设模型配置

EF Core 6.0 引入了一个预设模型配置。它允许你为一个给定的类型指定一次映射配置。例如,在处理值对象时,它可能很有帮助。

public class ExampleContext : DbContext
{public DbSet<Person> People { get; set; }public DbSet<Product> Products { get; set; }protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder){configurationBuilder.Properties<string>().HaveMaxLength(500);configurationBuilder.Properties<DateTime>().HaveConversion<long>();configurationBuilder.Properties<decimal>().HavePrecision(12, 2);configurationBuilder.Properties<Address>().HaveConversion<AddressConverter>();}
}
public class Product
{public int Id { get; set; }public decimal Price { get; set; }
}
public class Person
{public int Id { get; set; }public string FirstName { get; set; }public string LastName { get; set; }public DateTime BirthDate { get; set; }public Address Address { get; set; }
}
public class Address
{public string Country { get; set; }public string Street { get; set; }public string ZipCode { get; set; }
}
public class AddressConverter : ValueConverter<Address, string>
{public AddressConverter(): base(v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null),v => JsonSerializer.Deserialize<Address>(v, (JsonSerializerOptions)null)){}
}

10已编译模型

在 EF Core 6.0 中,你可以生成已编译的模型(compiled models)。当你有一个大的模型,而你的 EF Core 启动很慢时,这个功能是有意义的。你可以使用 CLI 或包管理器控制台来做。

public class ExampleContext : DbContext
{public DbSet<Person> People { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder options){options.UseModel(CompiledModelsExample.ExampleContextModel.Instance)options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=SparseColumns;Trusted_Connection=True;");}
}
public class Person
{public int Id { get; set; }public string FirstName { get; set; }public string LastName { get; set; }
}

CLI:

dotnet ef dbcontext optimize -c ExampleContext -o CompliledModels -n CompiledModelsExample

Package Manager Console:

Optimize-DbContext -Context ExampleContext -OutputDir CompiledModels -Namespace CompiledModelsExample

更多关于已编译模型及其限制的介绍:

https://devblogs.microsoft.com/dotnet/announcing-entity-framework-core-6-0-preview-5-compiled-models/
https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-6.0/whatsnew#limitations

11结尾

你可以在我的 GitHub 找到本文所有示例代码:

https://github.com/okyrylchuk/dotnet6_features/tree/main/EF%20Core%206#miscellaneous-enhancements

原文:bit.ly/3KAVnrG
作者:Oleg Kyrylchuk
翻译:精致码农

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/292042.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DS5020配置集群存储

一、方案设计 计划给某公司服务器制作集群&#xff0c;存储划分大致如下&#xff1a; 1、 将存储磁盘制作为raid5&#xff1b; 2、 划分两个Storage Partition给两类集群使用&#xff0c;一类为数据库服务&#xff0c;一类为各种应用服务 二、存储的连接 1、存储的简介 Serial …

RequireJS首次加载偶尔失败

现象&#xff1a;第一次加载JS文件&#xff0c;首次加载偶尔失败&#xff1b; 原因&#xff1a;require([jquery, operamasks, zTree, jQueryCookie]&#xff0c;中前后引用同步加载&#xff1b; 解决方式&#xff1a;shim声明前置加载&#xff1b; 配置如下&#xff1a; requi…

linux之file命令总结

解释&#xff1a; file是通过查看文件的头部内容&#xff0c;来获取文件的类型使用file命令可以知道某个文件究竟是二进制&#xff08;ELF格式&#xff09;的可执行文件, 还是Shell Script文件&#xff0c;或者是其它的什么格式。 file能识别的文件类型&#xff1a;目录、Shel…

优化.NET 应用程序 CPU 和内存的11 个实践

https://michaelscodingspot.com/cpu-bound-memory-bound/优化.NET 应用程序 CPU 和内存的11 个实践凡事都有其限度&#xff0c;对吧&#xff1f;汽车只能开这么快&#xff0c;进程只能使用这么多内存&#xff0c;程序员只能喝这么多咖啡。我们的生产力受到资源的限制&#xff…

陈省身:三角形内角和不等于180°

全世界只有3.14 % 的人关注了爆炸吧知识三角形外角和为360作为公认的劳模&#xff0c;平日里&#xff0c;超模君不但要码字&#xff0c;工作之余还要监督表妹做作业&#xff0c;也难怪表妹成绩总是能名列前茅。今天表妹做作业时&#xff0c;遇到一道判断题&#xff1a;“三角形…

跟我学PHP第二篇- 配置Mysql以及PHP WampServer篇(1)

大家好&#xff0c;昨天我给大家介绍了如何去安装ZEND STUDIO&#xff0c;下面昨天文章的链接&#xff1a; http://www.cnblogs.com/kmsfan/p/zendStudio.html 本节为配置的第一部分&#xff0c;还没有讲完全部&#xff0c;因为个人工作比较忙&#xff0c;没有一整天时间写博客…

linux之查看文件大小和磁盘大小总结

1 、查看文件大小 使用du命令,查看该目录以及子目录文件的大小 du -h 如果只需要快速查看这个目录占用大小&#xff0c;可用下面命令 du -sh 比如我们查看xiaoyun这个文件大小 2、查看电脑磁盘大小 使用下面命令 df -h 效果如下图 很明显系统装载/dev/sda2下

YARP(Yet Another Reverse Proxy)是使用 .NET 构建的高度可定制的反向代理

点击上方蓝字关注我们&#xff08;本文阅读时间&#xff1a;16分钟)YARP 1.0已经发布了&#xff0c;现在可以从 NuGet 下载。YARP&#xff08;Yet Another Reverse Proxy&#xff09;是使用 .NET 构建的高度可定制的反向代理。YARP 与其他反向代理的最大区别在于它是如何构建和…

电影院里为何有散落的青瓜?

1 摄像头&#xff1a;你套个袋子我就认不出来了吗&#xff1f;▼2 路边惊现大熊猫&#xff01;&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼3 好一个驼小姐&#xff08;via.豆瓣社死小组满杯草莓&#xff09;▼4 学弟的理解也不是无迹可寻▼5 台湾人过生日的方…

java中List、Map、Set、Collection、Stack、Queue等的使用

java中这几个东西是比较常用的&#xff0c;虽然我用的不多&#xff0c;也正是因为用的不多&#xff0c;所以我一直搞不清楚他们之间的具体用法以及相互之间的关系&#xff0c;现在特单独作为一个东西来总结一下。 本文参考一下资料&#xff1a; 1.《java编程思想》一书第11章 2…

开发文档模板_需求文档模板一堆什么样的适合你呢?

产品经理的日常中用的最多的是产品需求文档&#xff0c;这个文档应该可以说是产品经理将需求落到是明面上的一步。我们的文档需要给相关的人员进行共同的看&#xff0c;不然文档就没有存在的意义了&#xff0c;文档不只是简单的线框图和一些自己也看不明白的词汇。实际中很少开…

Briefly unavailable for scheduled maintenance message after doing automatic upgrade

为什么80%的码农都做不了架构师&#xff1f;>>> 今天突然不能打开wordpress&#xff0c;报了“Briefly unavailable for scheduled maintenance message after doing automatic upgrade” 这个错误&#xff0c;一下懵逼了。 Google之后&#xff0c;发现是wordpress…

搞IT的技术人员为什么会如此苦逼

http://www.cnblogs.com/springmvc-hibernate/archive/2012/05/10/2493733.html —————————————————————————————————————————————————————— 为什么苦逼&#xff1f; 原因一大堆&#xff0c;对于外部的因数&#xff0c;我…

为什么越来越多的开发者选择使用Spring Boot

Web应用开发背景 使用Java做Web应用开发已经有近20年的历史了&#xff0c;从最初的Servlet1.0一步步演化到现在如此多的框架&#xff0c;库以及整个生态系统。经过这么长时间的发展&#xff0c;Java作为一个成熟的语言&#xff0c;也演化出了非常成熟的生态系统&#xff0c;这…

【Blog.Core开源】快速预览Admin界面效果

( 半盏屠苏犹未举&#xff0c;灯前小草写桃符 )书接上文《【Blog.Core开源】开发插件&#xff0c;给Swagger加权》&#xff0c;在上篇文章中&#xff0c;我们给项目的接口文档增加了一个控制界面&#xff0c;可以输入用户名密码&#xff0c;这样也算是简单的一个加密控制了&…

视图添加字段_Odoo开发教程2-为模型添加字段

开启开发者模式后&#xff0c;我们可通过菜单 Settings > Technical > Database Structure > Models来查看模型的定义。这时搜索 res.partner(未安装其它应用的情况下第一个即是)&#xff0c;对应的模型描述为 Contact。点击打开表单视图&#xff0c;这时就可以看到 p…

linux之通过htop操作进程使用总结

1、htop介绍 top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器,htop比top更加人性化,有具体界面可以操作,读者可以先使用top看下效果,然后再安装htop. 2、安装htop 输入下面命令 sudo apt-get install htop 3、效…

6大奖项!首届 .NET 黑客松大赛圆满收官!

.NET Conf China 2021 是面向开发人员的社区峰会&#xff0c;基于 .NET Conf 2021&#xff0c;庆祝 .NET 6 的发布和回顾过去一年来 .NET 在中国的发展。峰会由来自北京、上海、苏州、深圳、武汉、广州、青岛、烟台、杭州等各地区的 .NET 技术社区共同发起举办&#xff0c;由微…