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. Html5游戏框架createJS组件--EaselJS

    CreateJS库是一款HTML5游戏开发的引擎,是一套可以构建丰富交互体验的HTML5游戏的开源工具包,旨在降低HTML5项目的开发难度和成本,让开发者以熟悉的方式打造更具现代感的网络交互体验. 掌 ...

  2. 亿级 Web 系统搭建:单机到分布式集群

    本文内容 Web 负载均衡 HTTP 重定向 反向代理 IP 负载均衡 DNS 负载均衡 Web 系统缓存机制的建立和优化 MySQL 数据库内部缓存 搭建多台 MySQL 数据库 MySQL 数据库 ...

  3. 《Unix&Linux大学教程》学习笔记5 :正则表达式

    1:Unix下正则表达式规则

  4. 利用ConcurrentHashMap来实现一个ConcurrentHashSet

    利用ConcurrentHashMap来实现一个ConcurrentHashSet package hashset; import java.io.Serializable; import java. ...

  5. cache line 伪共享

    https://blog.csdn.net/qq_27680317/article/details/78486220认识CPU Cache CPU Cache概述 随着CPU的频率不断提升,而内存的访 ...

  6. 【RS】Sparse Probabilistic Matrix Factorization by Laplace Distribution for Collaborative Filtering - 基于拉普拉斯分布的稀疏概率矩阵分解协同过滤

    [论文标题]Sparse Probabilistic Matrix Factorization by Laplace Distribution for Collaborative Filtering  ...

  7. 书记查询的App设计

    表示学习Andriod没有头绪,看书看着看着都觉得大部分是些item的介绍,看过去之后会完全忘记,还是自己做个小东西进行实际开发学习和掌握起来会比较快. PC端的软件已经做好,当然因为PC屏幕较大,手 ...

  8. OpenLayers 官网例子的中文详解

    https://segmentfault.com/a/1190000009679800?utm_source=tag-newest 当你希望实现某种功能的时候,即使你对 openlayers 几乎一窍 ...

  9. 适配器模式在Android中的应用

    工资翻倍篇之适配器模式 先了解一下适配器的基本概念,然后再详细分析一些适配器的样例,最后通过Android开发中经常使用的适配器模式进行分析,保证对适配器模式理解透彻. 适配器模式可分为三类:类的适配 ...

  10. CentOS下如何查看并杀死僵尸进程

    昨天服务器到期,之前的服务器由于空间小,不能满足现在的服务要求,就新购买了一个服务器,目前正在调试安装中! 在调试过程中,发现系统中有很多僵尸进程,现在就是找出这些僵尸进程,并将其杀死. 用top查看 ...