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变化的更多相关文章

  1. EF Core 的 Code First 模式

    0 前言 本文正文第一节,会对 Code First 进行基本的介绍,以及对相关名词进行说明,读者一开始可以不用在这里消耗过多时间,可以先操作一遍例子,再回过头理解. 第二节,以一个简单的例子,展示 ...

  2. Asp.net Core 通过 Ef Core 访问、管理Mysql

    本文地址:http://www.cnblogs.com/likeli/p/5910524.html 环境 dotnet Core版本:1.0.0-preview2-003131 本文分为Window环 ...

  3. EntityFramework Core技术线路(EF7已经更名为EF Core,并于2016年6月底发布)

    官方文档英文地址:https://github.com/aspnet/EntityFramework/wiki/Roadmap 历经延期和更名,新版本的实体框架终于要和大家见面了,虽然还有点害羞.请大 ...

  4. net Core 通过 Ef Core 访问、管理Mysql

    net Core 通过 Ef Core 访问.管理Mysql 本文地址:http://www.cnblogs.com/likeli/p/5910524.html 环境 dotnet Core版本:1. ...

  5. .net ef core 领域设计代码转换(上篇)

    一.前言 .net core 2.0正式版已经发布几个月了,经过研究,决定把项目转移过来,新手的话可以先看一些官方介绍 传送门:https://docs.microsoft.com/zh-cn/dot ...

  6. 在.NET Core类库中使用EF Core迁移数据库到SQL Server

    前言 如果大家刚使用EntityFramework Core作为ORM框架的话,想必都会遇到数据库迁移的一些问题. 起初我是在ASP.NET Core的Web项目中进行的,但后来发现放在此处并不是很合 ...

  7. [翻译 EF Core in Action 1.10] 应该在项目中使用EF Core吗?

    Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...

  8. [翻译 EF Core in Action 1.11] 何时不应该使用EF Core

    Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...

  9. [翻译 EF Core in Action 1.9] 掀开EF Core的引擎盖看看EF Core内部是如何工作的

    Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...

随机推荐

  1. 【Spark】榨干Spark性能-driver、exector内存突破256M

    榨干Spark性能-driver.exector内存突破256M spark driver memory 256m_百度搜索 Spark executor.memory - CSDN博客 sparkd ...

  2. Python多进程库multiprocessing中进程池Pool类的使用[转]

    from:http://blog.csdn.net/jinping_shi/article/details/52433867 Python多进程库multiprocessing中进程池Pool类的使用 ...

  3. 腾讯QQ会员中心g_tk32算法【C#版】

    最近用C#写qq活动辅助类程序,碰到了会员签到的gtk算法不一样,后来网上找了看,发现有php版的(https://www.oschina.net/code/snippet_1378052_48831 ...

  4. R语言编程艺术#02#矩阵(matrix)和数组(array)

    矩阵(matrix)是一种特殊的向量,包含两个附加的属性:行数和列数.所以矩阵也是和向量一样,有模式(数据类型)的概念.(但反过来,向量却不能看作是只有一列或一行的矩阵. 数组(array)是R里更一 ...

  5. 如何禁止VS显示“You have mixed tabs and spaces. Fix this?”

    如何禁止VS显示“You have mixed tabs and spaces. Fix this?” VS2013 版本的解决方案: Vs2013  IDE下,编辑C++的工程源码,在打开文件的时候 ...

  6. Disruptor学习笔记

    前言 以前一直听说有Disruptor这个东西,都说性能很强大,所以这几天自己也看了一下. 下面是自己的学习笔记,另外推荐几篇自己看到写的比较好的博客: Disruptor——一种可替代有界队列完成并 ...

  7. Docker 使用Docker知识简易部署一个LNMP平台

    1.自定义网络 docker network create lnmp 2.创建Mysql数据库容器(这里我们首先得创建一个mysql-vol数据卷) docker volume create mysq ...

  8. eclipse开发android入门学习

    1.device窗体            查看android执行情况的窗体和DDMS内容一致 2.android.bat             在adb路径下执行adb操作,实现android系统 ...

  9. [k8s]zookeeper集群在k8s的搭建(statefulset模式)-pod的调度

    之前一直docker-compose跑zk集群,现在把它挪到k8s集群里. docker-compose跑zk集群 zk集群in k8s部署 参考: https://github.com/kubern ...

  10. 阅读《深入应用C++11:代码优化与工程级应用》

    虽然一直是写C++的,但是却对C++11了解的不是太多,于是从图书馆借了本书来看 这本书分两大部分: 一.C++11的新特性讲解 二.工程级代码中C++11的应用 这样的安排很合理,第一部分把新特性讲 ...