前言

在项目中用到EntityFramework Core都是现学现用,及时发现问题及时测试,私下利用休闲时间也会去学习其他未曾遇到过或者用过的特性,本节我们来讲讲在EntityFramework Core 1.1中出现了哪些新特性供我们使用。

EntityFramework Core 1.1新特性探讨

DbSet.Find

在EF 6.x中也有此方法的实现,在EF Core 1.1中也同样对此方法进行了实现,为什么要拿出来讲呢,当然也有其道理,我们一起来看看。在仓储中我们实现Find这个方法,如下:

        public virtual T Find(int Key)
{
return _context.Set<T>().Find(Key);
}

此时我们来查询Blog中主键等于1的数据。

    var blog1 = _blogRepository.Find();

此时我们通过SQL Server Profiler监控得到如下SQL。

我们看到通过Find方法来查询主键等于1的数据时,声明了一个变量然后再来进行设置变量值进行查询,没毛病,上述我们是直接通过Find方法来实现,下面我们通过其他几种方法来实现。如下:

        public T GetSingle(int id)
{
return _context.Set<T>().FirstOrDefault(x => x.Id == id);
}
 var blog = _blogRepository.GetSingle();

此时和上述Find方法执行的SQL无任何区别,我们先别着急下结论,我们再来通过lambda表达式来实现看看。

        public T GetSingle(Expression<Func<T, bool>> predicate)
{
return _context.Set<T>().FirstOrDefault(predicate);
}
 var blog = _blogRepository.GetSingle(d => d.Id == );

此时我们再来看看生成的SQL语句。

此时生成的SQL语句没有声明变量看起来非常清爽,同时看过dudu老大刚不久写过在EF Core中我们声明的的lambda表达式中的参数就是我们查询表的别名,确实是如此,不知道你发现了没有。既然以上有多种实现且利用lambda表达式实现更加清爽,那么为何还要搞出一个Find方法呢,请继续往下看。

  var blog = _blogRepository.GetSingle(d => d.Id == );
var blog1 = _blogRepository.Find();

当我们第一次查询了主键等于1的数据时,我们第二次通过Find方法再来进行查询时通过监控SQL Server Profiler,你会发现并未生成任何SQL语句,这说明什么呢,说明EF Core团队给出Find方法的目的在于:当实体已经被加载到上下文中时,我们通过Find方法再去查询数据时此时不会再去数据库中进行查询。所以当我们利用主键查询数据时利用Find方法会减少对数据库的多次请求。

ICollection<T>(集合类型映射支持)

在之前EF版本中我们都是进行如下声明字段

    public class Blog : IEntityBase
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Url { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}

我们知道在EF Core中已经不存在延迟加载这一概念,所以请用了EF Core的童鞋将virtual关键字去掉。同时我们在映射集合时一直以来都统一用的ICollection<T>,但是在EF Core中不再有此局限性,我们进行如下定义:

    public class Blog : IEntityBase
{
public int Id { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public IEnumerable<Post> Posts { get; set; }
}

通过如上我们知道现在支持了IEnumerable<T>集合的映射。当然这里有个前提,其具体集合类必须实现ICollection接口,否则EntityFramework Core将无法进行填充。

Mapping to Fileds(映射到字段)

这个特性应该是前所未有,只有在EF Core 1.1中才出现,我们详细讲解下Backing Fileds(我们暂且将其翻译为返回字段)特性。自从有了如下自动属性的出现,就方便了我们许多。

 public string Url { get; set; }

什么是返回字段(Backing Fileds)特性,我们先看下原始为字段配置属性的情况如下:

private string _url;

public string Url
{
get { return _url; }
set { _url = value; }
}

Backing Fileds特性允许EF Core读或者写数据到字段中而不是属性中。也就是说如上EF Core将数据读写到_url字段中而不是Url中。默认情况下满足以下四种规则都会配置成Backing Fileds。

  • _<camel-cased property name>
  • _<property name>
  • m_<camel-cased property name>
  • m_<property name>

比如属性为UserName,那么对应的Backing Fileds则依次是:_userName,_UserName,m_userName,m_UserName。配置Backing Fileds后,当从数据库查询类实例后将直接将其对应数据写到字段中,在其他时候当EF Core需要读或者写值时有可能使用属性,例如EF需要更新一个属性上的值时,此时将使用属性的set访问器,如果属性仅仅只是只读,那么将值写到字段中。例如如下配置Backing Fileds即_validateUrl。

class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.Url)
.HasField("_validatedUrl");
}
} public class Blog
{
private string _validatedUrl; public int BlogId { get; set; } public string Url
{
get { return _validatedUrl; }
} public void SetUrl(string url)
{
using (var client = new HttpClient())
{
var response = client.GetAsync(url).Result;
response.EnsureSuccessStatusCode();
} _validatedUrl = url;
}
}

我们也可以在映射中配置使用属性还是字段,如下:

modelBuilder.Entity<Blog>()
.Property(b => b.Url)
.HasField("_validatedUrl")
.UsePropertyAccessMode(PropertyAccessMode.Field);

若我们在实体中没有属性,此时我们可以通过字段来存储数据。我们通过映射中的Porperty(...)来指定字段名称,若没有属性,此时EF Core将会查找字段,如下:

class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property("_validatedUrl");
}
} public class Blog
{
private string _validatedUrl; public int BlogId { get; set; } public string GetUrl()
{
return _validatedUrl;
} public void SetUrl(string url)
{
using (var client = new HttpClient())
{
var response = client.GetAsync(url).Result;
response.EnsureSuccessStatusCode();
} _validatedUrl = url;
}
}

讲了这么多Backing Fileds特性,不知道看到本篇文章的你清楚了它的作用是什么,为什么要提出Backing Fileds特性,它存在的价值或者说用途是做什么呢,就我个人的理解的话,提出Backing Fileds的多数场景在:如果属性只读,我们需要通过其他逻辑操作来获取其值,但是我们没有一个桥梁来赋予其值,此时我们就需要Backing Fileds来完成。希望看到此文的你有更多见解的话,请留下评论,一起探讨。这里我们结合上述IEnumerable<T>来进一步讲解Backing Fileds。我们在Blog类中是如下定义。

    public class Blog : IEntityBase
{
public int Id { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public IEnumerable<Post> Posts { get; set; }
}

我们知道对于导航属性Posts更多的是通过Inlcude来查询出Posts,所以在这里我们完全不需要set访问器以便减少对Posts反编译为Set方法,我们完全可以改造如下:

 public IEnumerable<Post> Posts { get; } =  new List<Post>();

话又说回来了,如果我们万一需要对Post进行一些操作,那么在这种情况下该如何是好呢,此时我们通过暴露IEnumerable<Blog>导航属性,然后借助该导航属性的Backing Fileds来对Post进行操作,改造如下:

    public class Blog : IEntityBase
{
private readonly List<Post> _posts = new List<Post>();
public int Id { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public IEnumerable<Post> Posts => _posts;
public void AddPost(Post post)
{
// Do some buisness your logic
_posts.Add(post);
}
}

我们实际来操作一下,查询Blog数据以及导航属性Post数据。

        public virtual IEnumerable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = _context.Set<T>();
foreach (var includeProperty in includeProperties)
{
query = query.Include(includeProperty);
}
return query.AsEnumerable();
}

我们进行如下查询:

 var blog = _blogRepository.GetSingle(d => d.Id == , d => d.Posts);

我们上述稍微改造了一下,为了以免查询出现错误,测试查询一下,如下,没毛病。

显式加载(Explicit Loading)

貌似显式加载没有什么应用的场景,不知道是否是应对某些特定的场景而给,它只是加载被上下文跟踪实体的导航属性,通过Include我们也可以实现,如下:

            var blog = _efCoreContext.Set<Blog>().Find();
_efCoreContext.Entry(blog).Collection(b => b.Posts).Load();
_efCoreContext.Entry(blog).Reference(b => b.Posts).Load();

连接弹性(Connection resiliency)

所谓的连接弹性则是执行数据库命令失败时我们可以重试,我们可以在OnConfiguring或者Startup.cs中设置,如下:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(
"connection string",
options => options.EnableRetryOnFailure());
}

SQL Server内存优化表支持

内存优化表是SQL Server的一个特性,它将整个表驻留在内存中,在磁盘上保留着对表的副本,主要是用于持久化,在数据库恢复时(比如重启)在内存优化表中的数据从磁盘上仅仅只是进行读取。比如对Blog表进行内存优化设置,如下:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.ForSqlServerIsMemoryOptimized();
}

将实体映射到内存优化中的表,当使用EF Core基于我们的模型创建数据库时,此时这些实体也将在内存优化表中创建一份。

简化服务更换(Simplify switch services)

在EF Core 1.0中就可以实现服务更换,但是略显复杂,在EF Core 1.1中替换服务类似于依赖注入一样,如下:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("connection string"); optionsBuilder.ReplaceService<SqlServerTypeMapper, MyCustomSqlServerTypeMapper>();
}

在EF 6.x之前版本中因为导航属性的存在很容易导致循环引用,所以对于EF Core同样是如此我们需要在Startup.cs中忽略循环引用,如下:

 services.AddMvc()
.AddJsonOptions(
options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);

总结

本节我们比较详细的讲解了EF Core 1.1中新添加或改善的特性,我们重点讲述了Backing Fileds特性。

EntityFramework Core 1.1有哪些新特性呢?我们需要知道的更多相关文章

  1. net core 3.0 之Grpc新特性小试牛刀

      相信微服务大家伙都有听说和知道,好处弊端咱也不多说了,Grpc算是一个比较全面的微服务框架,也得到微软的支持 总结下来就是,跨平台,可靠,通信快,扩展性强,网络消耗小,模板多语言通用 光说好处,没 ...

  2. Asp.Net Core 7 preview 4 重磅新特性--限流中间件

    前言 限流是应对流量暴增或某些用户恶意攻击等场景的重要手段之一,然而微软官方从未支持这一重要特性,AspNetCoreRateLimit这一第三方库限流库一般作为首选使用,然而其配置参数过于繁多,对使 ...

  3. EntityFramework Core 2.0全局过滤(HasQueryFilter)

    前言 EntityFramework Core每一次版本的迭代和更新都会带给我们惊喜,每次都会尽量满足大部分使用者的需求.在EF Core 2.0版本中出现了全局过滤新特性即HasQueryFilte ...

  4. EntityFramework Core 2.0执行原始查询如何防止SQL注入?

    前言 接下来一段时间我们来讲讲EntityFramework Core基础,精简的内容,深入浅出,希望为想学习EntityFramework Core的童鞋提供一点帮助. EntityFramewor ...

  5. EntityFramework Core 2.0自定义标量函数两种方式

    前言 上一节我们讲完原始查询如何防止SQL注入问题同时并提供了几种方式.本节我们继续来讲讲EF Core 2.0中的新特性自定义标量函数. 自定义标量函数两种方式 在EF Core 2.0中我们可以将 ...

  6. EntityFramework Core 1.1+ Backing Fields(返回字段)

    前言 通过我发表的博文可知最近一段时间会将持续讲解EntityFramework Core特性,在此之前我提到过Backing Fields,回头翻了翻感觉写的还不够好,于是乎再来讲解一番,也是自己再 ...

  7. asp.net core新特性(1):TagHelper

    进步,才是人应该有的现象.-- 雨果 今天开始,我就来说说asp.net core的新特性,今天就说说TagHelper标签助手.虽然学习.net,最有帮助的就是microsoft的官方说明文档了,里 ...

  8. Entity Framework Core 2.0 新特性

    本文翻译来自:https://docs.microsoft.com/en-us/ef/core/what-is-new/index 一.模型级查询过滤器(Model-level query filte ...

  9. Asp.net Core中SignalR Core预览版的一些新特性前瞻,附源码(消息订阅与发送二进制数据)

    目录 SignalR系列目录(注意,是ASP.NET的目录.不是Core的) 前言 一晃一个月又过去了,上个月有个比较大的项目要验收上线.所以忙的脚不沾地.现在终于可以忙里偷闲,写一篇关于Signal ...

随机推荐

  1. windows服务器下IIS7 安装URL Rewrite(URL重写)模块

    URL Rewrite Module是一个基于规则的URL重写引擎,用于在URL被Web服务器处理之前改变请求的URL.对于动态Web应用程序,它可以为用户和seo/seo.html" ta ...

  2. Keil C动态内存管理机制分析及改进(转)

    源:Keil C动态内存管理机制分析及改进 Keil C是常用的嵌入式系统编程工具,它通过init_mempool.mallloe.free等函数,提供了动态存储管理等功能.本文通过对init_mem ...

  3. df换行问题的设置

    df是linux下用来查磁盘空间的命令,而在使用了LVM分区或网络挂载的情况下,再用df取分区的使用率时,发现有些分区显示换行了,这样会导致通过脚本取的数据不对. [root@ ]# df -h Fi ...

  4. xcode 6 出现的新问题

    1.prefix.pch文件的使用 [1].需要自己创建 点击new file-->选择IOS中的Other选项卡,选择PCH File [2].创建完后需要设置一下才能成功 Prefix He ...

  5. Extjs4中的store

      Extjs 4引入新的数据包,其中新增了不少新类并对旧有的类作出了修整.使数据包更强大和更容易使用.  本章我们将学习一下内容: 2.1. 概述新特性      Extjs4的数据包引入了如Mod ...

  6. 12、手把手教你Extjs5(十二)执行菜单命令在tabPanel中显示模块

    上面设计好了一个模块的主界面,下面通过菜单命令的执行来把这个模块加入到主界面当中.在MainModule.js中有一个函数,生成了当前的菜单数据: // 根据data.systemMenu生成菜单条和 ...

  7. jqGrid添加自定义按钮

    用法: <script> ... jQuery("#grid_id").navGrid("#pager",...).navButtonAdd(&qu ...

  8. jquery之选项卡效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. S3C2440的RTC解析

    位二-十进制交换码(BCD)值数据给CPU.这些数据包括年.月.日.星期.时.分和秒的时间信息.RTC单元工作在外部32.768kHz晶振并且可以执行闹钟功能 实时时钟模块保存的数据是DCD码形式. ...

  10. MQ-2烟雾传感器启动

    MQ-2气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2).当传感器所处环境中 存在可燃气体时,传感器的电导率随空气中可燃气体浓度的增加而增大.使用简单的电路即可将电导率的 变化 ...