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 ...
随机推荐
- GeoHash原理和可视化显示
最近在做附近定位功能的产品,geohash是一个非常不错的实现方式.查询资料,发现阿里的这篇文章讲解的很好.但文中并没有给出geohash显示的工具.无奈,也没有查到类似的.只好自己简单显示一下,方便 ...
- 【asp.net core】Publish to a Linux-Ubuntu 14.04 Server Production Environment
Submary 又升级了,目录结构有变化了 . project.json and Visual Studio 2015 with .NET Core On March 7, 2017, the .NE ...
- Oracle11g登录名和密码不区分大小写
问题描述: oracle11g对账户密码实行大小写识别,烦的一比!想移除此限制 问题解决: oracle 11g以前的版本的用户名和密码是不区分大小写!oracle 11g 用户名和密码默认区分大小写 ...
- SciTe设置
对于新手来说,如果没有正确的配置,它就不是那么好使,比如选择中文时候出现乱码,缩进也不是你想象中的样子. 由于配置参数不是采用图形界面,而且出看配置代码会比较混乱,所以大家要睁大眼睛好好看咯- 程序中 ...
- java webdriver的api的封装
我们来看一下官网提供的代码写法,即最原始的写法: driver.findElement(By.id("kw")).click() 这样写是没任何问题的,但这样没有把元素对象,数据, ...
- CSS之定位,relative/absolute/fixed的用法
其实position的值有四个,static/relative/absolute/fixed,而static是默认值,不算具有有定位属性,这里就不讲了. 定位其实就是跟元素设置定位属性,然后设置其对位 ...
- php http请求封装
/** * 发送HTTP请求方法,目前只支持CURL发送请求 * @param string $url 请求URL * @param array $params 请求参数 * @param strin ...
- SNF快速开发平台MVC-集成了百度开源项目echars
百度开源项目echars图表样式非常丰富,而且开源免费.非常好.所以在我们框架当中也进行了集成echars完成图表任务. 我们进行了两次封装,利于我们开发使用.我也看到过有些架构师 按echars里的 ...
- 开源的.NET任务调度框架-HangFire
什么是Hangfire Hangfire 是一个开源的.NET任务调度框架,目前1.6+版本已支持.NET Core.内置提供集成化的控制台,方便后台查看及监控: 另外,Hangfire包含三大核心组 ...
- Atitit 技术经理职责与流程表总结
Atitit 技术经理职责与流程表总结 1. (最重要) 理念 价值观建设 ***团队文化建设2 1.1. 加强跨项目组员沟通 ,防止重复劳动2 1.2. 活动聚餐2 2. (重要)方向建设 技术 ...