EF Core 2.1变化
EF Core 2.1随.NET Core 2.1一起发布,本篇文章总结一下EF Core的新增功能,先从简单的开始说。
一、延迟加载
延迟加载不用介绍了吧,直接看一下怎样配置吧。EF Core 2.1默认是不允许延迟加载的,想要使用这个特性必须调用UseLazyLoadingProxies方法,这个扩展方法在 Microsoft.EntityFrameworkCore.Proxies 包中。
在Startup中配置:

public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TestContext>(options =>
{
options.UseLazyLoadingProxies().UseSqlServer("yourConnectionString");
});
}

也可在DbContext中重写OnConfiguring方法中配置:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLazyLoadingProxies().UseSqlServer("yourConnectionString");
}
配置好后在实体类中对应的属性上加上 virtual 关键字就OK,用法和EF6没区别。除了加 virtual 标记外,EF Core 2.1还可以通过 ILazyLoader 类型的对象来实现延迟加载,实现如下:

public class Person
{
public Person() { } public Person(ILazyLoader lazyLoader)
{
LazyLoader = lazyLoader;
} public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } private ILazyLoader LazyLoader { get; set; } private ICollection<Child> _children; public virtual ICollection<Child> Children
{
get => LazyLoader?.Load(this, ref _children);
set => _children = value;
}
}

ILazyLoader在 Microsoft.EntityFrameworkCore.Abstractions 程序集中。按照官方文档所述,除了注入 ILazyLoader 类型使用LazyLoader外还可以注入Action<object,string>类型来实现LazyLoader,但我尝试的时候报错,如果有尝试成功的希望能在留言区里留言,多谢。
二、支持GroupBy
这个特性就不多说了,使用方法和EF6没区别。
三、支持TransactionScope
这个特性也和EF6一样,终于可以随时随地使用事务了。
四、Data Seeding
这个功能是用来初始化数据的,在进行数据库迁移时,EF会往数据库中插入一些数据,实现如下:

public class PersonConfig : IEntityTypeConfiguration<Person>
{
public void Configure(EntityTypeBuilder<Person> builder)
{
builder.HasData(new Person[]
{
new Person
{
Id = 1,
Name ="张三",
Age = 30
}
});
}
}

使用EntityTypeBuilder下的HasData就可以实现该功能。但令人感到奇怪的是,就算Id是自增长的EF也会要求Id有值!而且也不支持同时插入子表的数据。

public class PersonConfig : IEntityTypeConfiguration<Person>
{
public void Configure(EntityTypeBuilder<Person> builder)
{
builder.HasData(new Person[]
{
new Person
{
Id = 1,
Name ="张三",
Age = 30,
Children = new List<Child>
{
new Child
{
Id = 1,
Name = "小张三",
Age = 5,
PersonId = 1
},
new Child
{
Id = 2,
Name = "小小张三",
Age = 1,
PersonId = 1
}
}
}
});
}
}

上面的代码,在进行数据迁移时,Children的数据不会插入到数据库中,不知道以后是否会支持关联属性的数据导入。
五、值转换
这个功能简单来说就是将属性的类型转换成数据库中的类型(比如枚举转换成字符串),实例中可以这样写:

public class Person
{
public Person() { } public Person(ILazyLoader lazyLoader)
{
LazyLoader = lazyLoader;
} public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public Gender Gender { get; set; } private ILazyLoader LazyLoader { get; set; } private ICollection<Child> _children; public virtual ICollection<Child> Children
{
get => LazyLoader?.Load(this, ref _children);
set => _children = value;
}
} public enum Gender
{
男,
女
}

然后再配置一下:

public class PersonConfig : IEntityTypeConfiguration<Person>
{
public void Configure(EntityTypeBuilder<Person> builder)
{
builder.Property(p => p.Gender).HasConversion(v => v.ToString(), v => (Gender)Enum.Parse(typeof(Gender), v)).IsRequired().HasMaxLength(2);
}
}

这里有个问题比较奇怪,我在配置类中加上这段配置并在HasData中给Gender赋值,使用Migration的时候发现如果不加 IsRequired 他居然不给我把Gender的数据给导入到数据库里面!!!
除了基本的枚举转字符串以外,EF Core还提供如下的转换类:
| BoolToZeroOneConverter | 将布尔值转换为0或1 |
| BoolToStringConverter | 将布尔值转换为字符串(Y或N) |
| BoolToTwoValuesConverter | 将布尔值转换为指定的两个值(没搞明白干嘛用的) |
| BytesToStringConverter | 将字节数组转换为Base64编码的字符串 |
| CastingConverter | 从一种类型转换到另一种类型(可以被C#互相转换的类型) |
| CharToStringConverter | char转为string |
| DateTimeOffsetToBinaryConverter | DateTimeOffset转为二进制的64位的值 |
| DateTimeOffsetToBytesConverter | DateTimeOffset转为字节数组 |
| DateTimeOffsetToStringConverter | DateTimeOffset转为字符串 |
| DateTimeToBinaryConverter | DateTime转为带有DateTimeKind的64位的值 |
| DateTimeToStringConverter | DateTime转为字符串 |
| DateTimeToTicksConverter | DateTime转为ticks |
| EnumToNumberConverter | 枚举转数字 |
| EnumToStringConverter | 枚举转字符串 |
| GuidToBytesConverter | Guid转字节数组 |
| GuidToStringConverter | Guid转字符串 |
| NumberToBytesConverter | 数字转字节数组 |
| NumberToStringConverter | 数字转字符串 |
| StringToBytesConverter | 字符串转字节数组 |
| TimeSpanToStringConverter | TimeSpan转字符串 |
| TimeSpanToTicksConverter | TimeSpan转ticks |
上面的这些对象的使用方式如下:
var converter = new EnumToStringConverter<Person>();
builder.Property(p => p.Gender).HasConversion(converter);
除了这种方式外,EF Core也支持直接指定类型,如:
builder.Property(p => p.Gender).HasConversion(string);
需要注意的是,不能将null进行转换,一个属性只能对应一个列做转换。
六、Query Types
这个功能用来查询数据库视图的。先创建个实体类:

public class Family
{
public int ParentId { get; set; } public string ParentName { get; set; } public int ParentAge { get; set; } public int ChildId { get; set; } public string ChildName { get; set; } public int ChildAge { get; set; }
}

根据实体类在数据库中创建视图就行(貌似Migration不支持创建视图),SQL我就不写了。然后创建个继承自 IQueryTypeConfiguration<> 的配置类,代码如下:

public class FamilyConfig : IQueryTypeConfiguration<Family>
{
public void Configure(QueryTypeBuilder<Family> builder)
{
builder.ToView("Family_View");
}
}

DbContext中使用 DbQuery<Family> 类型增加一个属性,运行下看看结果:

根据官方文档所述,该功能只能查询,不能增删改,不具有状态跟踪,不能包含具体查询类型的导航属性(既然不能有导航属性为啥这里有个lazyLoader...)。
本文总结的都是我认为有用的功能,EF Core 2.1新增的其他功能可以到移步至官方文档:https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-2.1
最后补充一个扩展方法,功能和EF6的AddFromAssembly方法相同。

private static bool IsIEntityTypeConfigurationType(Type typeIntf)
{
return typeIntf.IsInterface && typeIntf.IsGenericType && typeIntf.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>);
} public static void ApplyConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
{
//筛选出继承自IEntityTypeConfiguration的类型
IEnumerable<Type> types = assembly.GetTypes().Where(t => !t.IsAbstract && t.GetInterfaces().Any(it => IsIEntityTypeConfigurationType(it)));
Type typeModelBuilder = modelBuilder.GetType();
MethodInfo methodNonGenericApplyConfiguration = typeModelBuilder.GetMethods()
.Where(m => m.IsGenericMethod && m.Name == nameof(ModelBuilder.ApplyConfiguration) && m.GetParameters().Any(s => s.ParameterType.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>))).First();
foreach (var type in types)
{
object entityTypeConfig = Activator.CreateInstance(type);
//获取实体的类型
Type typeEntity = type.GetInterfaces().First(t => IsIEntityTypeConfigurationType(t)).GenericTypeArguments[0];
//通过MakeGenericMethod转换为泛型方法
MethodInfo methodApplyConfiguration = methodNonGenericApplyConfiguration.MakeGenericMethod(typeEntity);
methodApplyConfiguration.Invoke(modelBuilder, new[] { entityTypeConfig });
}
}

以上代码根据RuPeng.EFCore.Ext组件修改,该组件暂时不支持EF Core 2.1,GitHub已提交pr,不知道杨老师啥时候更新下。
EF Core 2.1变化的更多相关文章
- EF Core 的 Code First 模式
0 前言 本文正文第一节,会对 Code First 进行基本的介绍,以及对相关名词进行说明,读者一开始可以不用在这里消耗过多时间,可以先操作一遍例子,再回过头理解. 第二节,以一个简单的例子,展示 ...
- Asp.net Core 通过 Ef Core 访问、管理Mysql
本文地址:http://www.cnblogs.com/likeli/p/5910524.html 环境 dotnet Core版本:1.0.0-preview2-003131 本文分为Window环 ...
- EntityFramework Core技术线路(EF7已经更名为EF Core,并于2016年6月底发布)
官方文档英文地址:https://github.com/aspnet/EntityFramework/wiki/Roadmap 历经延期和更名,新版本的实体框架终于要和大家见面了,虽然还有点害羞.请大 ...
- net Core 通过 Ef Core 访问、管理Mysql
net Core 通过 Ef Core 访问.管理Mysql 本文地址:http://www.cnblogs.com/likeli/p/5910524.html 环境 dotnet Core版本:1. ...
- .net ef core 领域设计代码转换(上篇)
一.前言 .net core 2.0正式版已经发布几个月了,经过研究,决定把项目转移过来,新手的话可以先看一些官方介绍 传送门:https://docs.microsoft.com/zh-cn/dot ...
- 在.NET Core类库中使用EF Core迁移数据库到SQL Server
前言 如果大家刚使用EntityFramework Core作为ORM框架的话,想必都会遇到数据库迁移的一些问题. 起初我是在ASP.NET Core的Web项目中进行的,但后来发现放在此处并不是很合 ...
- [翻译 EF Core in Action 1.10] 应该在项目中使用EF Core吗?
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- [翻译 EF Core in Action 1.11] 何时不应该使用EF Core
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- [翻译 EF Core in Action 1.9] 掀开EF Core的引擎盖看看EF Core内部是如何工作的
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
随机推荐
- ORA-00959: tablespace 'TB01' does not exist
当前的表空间如下: SQL> select name from v$tablespace; NAME ---------------------------------------------- ...
- Class.forName和ClassLoader.loadClass的区别
Class的装载分了三个阶段,loading,linking和initializing,分别定义在The Java Language Specification的12.2,12.3和12.4. Cla ...
- Swift -- 中文版两大官方文档汇总
Swift官方文档由CocoaChina翻译小组精心翻译制作而成,目前两本文档中文版已全部完成!在此,我们对所有参与的译者.组织人员以及工作人员表示衷心的感谢!本文为您提供两本文档的在线阅读以及下载! ...
- JAVA中对List<Map<String,Object>>中的中文汉字进行排序
转载于:http://blog.csdn.net/flykos/article/details/54631573 参考:http://www.jb51.net/article/88710.htm 本篇 ...
- Rocket Typist for Mac(增强型文本快速输入工具)破解版安装
1.软件简介 Rocket Typist 是 macOS 系统上一款增强型文本快速输入工具,我们可以利用这款工具预先设置保存好很多日常生活学习或是工作中常用的文本片段,还能设定部分内容为变量,当 ...
- SNF快速开发平台MVC-EasyUI3.9之-WebApi身份验证问题解决方案
在我们的整体bs框架当中前端采用的是MVC+WebApi的处理方式.WebApi使用起来确实很方便但也会有新的麻烦事,就是身份验证. 如果没有启用身份认证,那么任何匿名用户只要知道了我们服务的url, ...
- Nginx-rtmp 直播媒体实时流实现
0. 前言 这段时间在搭建一个IPCamera项目服务器.视频点对点通话,客户端会查看设备端的音视频实时流.为了省流量,是通过P2P进行穿透.但是由于NAT设备的原因和IPV4的枯竭.有些设备是无法进 ...
- vue手写的轮播图片,解决已经修改data中的值,页面标签已绑定,但页面没效果
1.效果 2.index.html <!DOCTYPE html> <html lang="en"> <link> <meta chars ...
- 【iCore1S 双核心板_ARM】例程十三:SDIO实验——读取SD卡信息
实验现象: 核心代码: int main(void) { /* USER CODE BEGIN 1 */ HAL_SD_TransferStateTypedef State; /* USER CODE ...
- 一个相对通用的JSON响应结构,其中包含两部分:元数据与返回值
定义一个相对通用的JSON响应结构,其中包含两部分:元数据与返回值,其中,元数据表示操作是否成功与返回值消息等,返回值对应服务端方法所返回的数据. public class Response { pr ...