博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EF Core 2.1变化
阅读量:5150 次
发布时间:2019-06-13

本文共 7232 字,大约阅读时间需要 24 分钟。

EF Core 2.1随.NET Core 2.1一起发布,本篇文章总结一下EF Core的新增功能,先从简单的开始说。

一、延迟加载

延迟加载不用介绍了吧,直接看一下怎样配置吧。EF Core 2.1默认是不允许延迟加载的,想要使用这个特性必须调用UseLazyLoadingProxies方法,这个扩展方法在  包中。

在Startup中配置:

public void ConfigureServices(IServiceCollection services){    services.AddDbContext
(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
_children; public virtual ICollection
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
{ public void Configure(EntityTypeBuilder
builder) { builder.HasData(new Person[] { new Person { Id = 1, Name ="张三", Age = 30 } }); }}

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

public class PersonConfig : IEntityTypeConfiguration
{ public void Configure(EntityTypeBuilder
builder) {
       builder.HasData(new Person[] { new Person { Id = 1, Name ="张三", Age = 30, Children = new List
{ 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
_children; public virtual ICollection
Children { get => LazyLoader?.Load(this, ref _children); set => _children = value; }}public enum Gender{ 男, 女}

然后再配置一下:

public class PersonConfig : IEntityTypeConfiguration
{ public void Configure(EntityTypeBuilder
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
();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
{ public void Configure(QueryTypeBuilder
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
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,不知道杨老师啥时候更新下。

转载于:https://www.cnblogs.com/damsoft/p/9523213.html

你可能感兴趣的文章
301和302 Http状态有啥区别?
查看>>
字符串的操作时间格式化
查看>>
前端js文件添加版本号
查看>>
遗传算法
查看>>
【uWSGI】实战之Django配置经验
查看>>
教学反馈系统-阶段项目1
查看>>
Codeforces 1159E 拓扑排序
查看>>
bfs codeforces 754B Ilya and tic-tac-toe game
查看>>
Codeforces 505C
查看>>
移动端 移动web屏幕适配方案 随不同宽度的屏幕而改变
查看>>
iOS实现 抽屉效果 的滑动缩放、定位和还原
查看>>
软件测试理论(一)
查看>>
如何解决CRUD操作中与业务无关的字段赋值
查看>>
印度要求华为中兴批露企业所有者资料
查看>>
linux teminal keyword
查看>>
【AMAD】transitions -- 一个python实现的轻量级,面向对象的有限状态机
查看>>
如何使用Adobe Reader复制PDF文档上的文字
查看>>
PL/SQL学习(一)
查看>>
c#中的反射机制
查看>>
Java for LeetCode 160 Intersection of Two Linked Lists
查看>>