EntityFramework Core 1.1有哪些新特性呢?我们需要知道

前言

在项目中用到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(1);

此时我们通过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(1);

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

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

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

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

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

当我们第一次查询了主键等于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 == 1, d => d.Posts);

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

 

显式加载(Explicit Loading) 

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

            var blog = _efCoreContext.Set<Blog>().Find(1);
            _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特性。

时间: 2024-09-22 12:21:50

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

Oracle 12.2新特性掌上手册 - 第三卷 Core Improvements

编辑手记:Oracle 12.2 在内核上有许多创造性的改进,这些改进让数据库的操作更加高效便捷,同时一些面向智能运维和大数据的改进,则迈出了云和大数据时代的重要一步.在今年的DB-Engines的评选中,Oracle位居榜首,而我们从12.2的这些更新中便知道,Oracle是DBMS当之无愧的领导者. 注:文章内容来自官方文档翻译.若需要了解更多,请查阅官方文档. 1.Partition-Specific Near Real-Time Indexes(近实时索引的配置) 12.2中可以在分区级

EntityFramework 7 更名为EntityFramework Core(预发布状态)

前言 最近很少去学习和探索新的东西,尤其是之前一直比较关注的EF领域,本身不太懒,但是苦于环境比较影响自身的心情,所以迟迟没有下笔,但是不去学习感觉在精神层面缺少点什么,同时也有园友说EF又更新了,要我再写一篇,最终经过思想斗争后,还是花了一点时间去继续探索.本篇比较理论的去分享最近EF进展,后面有时间会继续关注EF团队在EF上的动向,并给出相对应的实例. EF Core 1.0.0 (1)EntityFramework是微软在.NET中推荐使用的数据访问技术,而EntityFramework

EntityFramework Core问题处理集锦(一)

前言 和大家脱离了一段时间,有时候总想着时间挤挤总是会有的,但是并非人愿,后面会借助周末的时间来打理博客,如有问题可以在周末私信我或者加我QQ皆可,欢迎和大家一起探讨,本节我们来讨论EF Core中的一些问题后面陆陆续续会将EF Core中需要注意的地方补充上来,有些是我一直以来比较疏忽的地方,不喜勿喷.用在实际项目中的时候才发现和平时所学有很大差异,靠着项目才能检验出真理. EntityFramework Core问题集锦 更新单个实体 更新单个实体的方式有两种: (1)查询出实体进行赋值更新

【译】Java 8的新特性—终极版

文/杜琪(简书作者) 原文链接:http://www.jianshu.com/p/5b800057f2d8 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者". 声明:本文翻译自Java 8 Features Tutorial – The ULTIMATE Guide,翻译过程中发现并发编程网已经有同学翻译过了:Java 8 特性 – 终极手册,我还是坚持自己翻译了一版(写作驱动学习,加深印象),有些地方参考了该同学的. Java 8 前言: Java 8 已经发布很久了,很

jQuery 1.4官方文档详细讲述新特性功能

为了庆祝jQuery的四周岁生日, jQuery的团队荣幸的发布了jQuery Javascript库的最新主要版本! 这个版本包含了大量的编程,测试,和记录文档的工作,我们为此感到很骄傲. 我要以个人的名义感谢 Brandon Aaron, Ben Alman, Louis-Rémi Babe, Ariel Flesler, Paul Irish, Robert Kati?, Yehuda Katz, Dave Methvin, Justin Meyer, Karl Swedberg, and

PHP5.0新特性(ZT)

php5 (一) Zend 2.0的诞生现在的PHP4所使用的基本文法是被称之为Zend 引擎的脚本编译引擎.这个就是PHP4的优良机能的原因之一,是作为对PHP3的改进而生成的一种语言.大家一直认为,PHP4的性能根据当初的目标,比PHP3有了很大的提升,在网络编程的世界里占据了很大的份额. 开发了Zend 引擎的Zend公司是在开发PHP4的同时,由PHP3的主要开发者Zeev Suraski和Andi Gutmans所创立的企业合并而来的.Zend的名称是由Zeev和Andi的名字合起来组

J2SE 1.5版本的新特性一览

j2se 到了2003的年末,J2SE1.5的beta版本就将发布了.这次发布和现在已经发布的J2SE1.4的两个更新1.4.1和1.4.2都如2003年的JavaOne大会预期的发布.如果你没有参加这次大会,或者想重新回顾一下,那么下面就是这次大会的简要内容. J2SE 1.4.1 and 1.4.2 Releases 当1.4.1(开发代号"Hopper")在2002年9月发布以及它的后续版本1.4.2(开发代号"Mantis")在2003年1月如期发布的时候,

OSGi Service Platform V4.2新特性

经过将近两年的准备,OSGi 联盟终于在 2009 年 9 月发布了最新版的 OSGi Service Platform V4.2 规范.其中,新的 Core Specification V4.2 规范中增加了 Framework launching,Service Hooks 等概念,并且对 Conditional Permission Admin 标准进行了改进和补充以方便安全管理和配置.此外,在企业专家组的大力推动下,新的 Service Compendium V4.2 规范中引入了 Bl

Spring 2.5的新特性:配置简化和基于注解的功能

简介 从诞生之初,Spring框架就坚守它的宗旨:简化企业级应用开发,同时给复杂问题提供强大的.非侵入性解决方案.一年前发布的Spring 2.0就把这些主题推到了一个新的高度.XML Schema的支持和自定义命名空间的使用大大减少了基于XML的配置.使用Java 5及更新版本java的开发人员如今可以利用植入了像泛型(generic)和注解等新语言特性的Spring库.最近,和AspectJ表达式语言的紧密集成,使得以非侵入方式添加跨越定义良好的Spring管理对象分组的行为成为可能. 新发