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 ...
随机推荐
- 【Spark】榨干Spark性能-driver、exector内存突破256M
榨干Spark性能-driver.exector内存突破256M spark driver memory 256m_百度搜索 Spark executor.memory - CSDN博客 sparkd ...
- Python多进程库multiprocessing中进程池Pool类的使用[转]
from:http://blog.csdn.net/jinping_shi/article/details/52433867 Python多进程库multiprocessing中进程池Pool类的使用 ...
- 腾讯QQ会员中心g_tk32算法【C#版】
最近用C#写qq活动辅助类程序,碰到了会员签到的gtk算法不一样,后来网上找了看,发现有php版的(https://www.oschina.net/code/snippet_1378052_48831 ...
- R语言编程艺术#02#矩阵(matrix)和数组(array)
矩阵(matrix)是一种特殊的向量,包含两个附加的属性:行数和列数.所以矩阵也是和向量一样,有模式(数据类型)的概念.(但反过来,向量却不能看作是只有一列或一行的矩阵. 数组(array)是R里更一 ...
- 如何禁止VS显示“You have mixed tabs and spaces. Fix this?”
如何禁止VS显示“You have mixed tabs and spaces. Fix this?” VS2013 版本的解决方案: Vs2013 IDE下,编辑C++的工程源码,在打开文件的时候 ...
- Disruptor学习笔记
前言 以前一直听说有Disruptor这个东西,都说性能很强大,所以这几天自己也看了一下. 下面是自己的学习笔记,另外推荐几篇自己看到写的比较好的博客: Disruptor——一种可替代有界队列完成并 ...
- Docker 使用Docker知识简易部署一个LNMP平台
1.自定义网络 docker network create lnmp 2.创建Mysql数据库容器(这里我们首先得创建一个mysql-vol数据卷) docker volume create mysq ...
- eclipse开发android入门学习
1.device窗体 查看android执行情况的窗体和DDMS内容一致 2.android.bat 在adb路径下执行adb操作,实现android系统 ...
- [k8s]zookeeper集群在k8s的搭建(statefulset模式)-pod的调度
之前一直docker-compose跑zk集群,现在把它挪到k8s集群里. docker-compose跑zk集群 zk集群in k8s部署 参考: https://github.com/kubern ...
- 阅读《深入应用C++11:代码优化与工程级应用》
虽然一直是写C++的,但是却对C++11了解的不是太多,于是从图书馆借了本书来看 这本书分两大部分: 一.C++11的新特性讲解 二.工程级代码中C++11的应用 这样的安排很合理,第一部分把新特性讲 ...