前言

在项目中用到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. 用curl测试rest服务时,

    query parameter总是只能得到第一个,原来是需要加引号,否则url中的&符号被理解为命令行中的后台执行.

  2. 高橋君とカード / Tak and Cards

    高橋君とカード / Tak and Cards Time limit : 2sec / Stack limit : 256MB / Memory limit : 256MB Score : 300 p ...

  3. FTP详解

    概述 FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为“文传协议”.用于Internet上的控制文件的双向传输.同时,它也是一个应用程序(Applicat ...

  4. highcharts分段显示不同颜色

    最近在做统计图的时候,碰到一个需求 类似如下: 就是在红色虚线框内的折线在不同区域用不同的颜色表示,并且是虚线. 开始定位为用highcharts库实现.确定用这个库后,开始在网上查资料,发现有类似的 ...

  5. (二)Jquery Mobile介绍以及Jquery Mobile页面与对话框

    Jquery Mobile介绍以及Jquery Mobile页面与对话框  一. Adobe Dreamweaver CS6 环境 最新版本的cs6会支持JM的使用,有自动提示功能,很强大.安装说明地 ...

  6. nginx location配置(URL)

    语法规则: location [=|~|~*|^~] /uri/ { … }= 表示精确匹配,这个优先级也是最高的^~ 表示uri以某个常规字符串开头,理解为匹配 url路径即可.nginx不对url ...

  7. 从url下载图片--java与python实现方式比较

    从url下载图片--java与python实现方式比较 博客分类: 技术笔记小点滴 javapython图片下载  一.java的实现方式 首先读取图片 //方式一:直接根据url读取图片 priva ...

  8. (简单) POJ 3268 Silver Cow Party,Dijkstra。

    Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to atten ...

  9. CodeForces 625A Guest From the Past

    贪心水题 #include <stdio.h> #include <algorithm> #include <string.h> #include <queu ...

  10. java调用C/C++写的dll(转)

    源:java调用C/C++写的dll Java语言本身具有跨平台性,如果通过Java调用DLL的技术方便易用,使用Java开发前台界面可以更快速,也能带来跨平台性. Java调用C/C++写好的DLL ...