前言
在项目中用到EntityFramework Core都是现学现用,及时发现问题及时测试,私下利用休闲时间也会去学习其他未曾遇到过或者用过的特性,本节我们来讲讲在EntityFramework Core 1.1中出现了哪些新特性供我们使用。
创新互联专注于企业营销型网站、网站重做改版、巴马网站定制设计、自适应品牌网站建设、HTML5、商城网站建设、集团公司官网建设、成都外贸网站制作、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为巴马等各大城市提供网站开发制作服务。
EntityFramework Core 1.1新特性探讨
DbSet.Find
在EF 6.x中也有此方法的实现,在EF Core 1.1中也同样对此方法进行了实现,为什么要拿出来讲呢,当然也有其道理,我们一起来看看。在
        public virtual T Find(int Key)
        {            return _context.Set().Find(Key);
        } 此时我们来查询Blog中主键等于1的数据。
var blog1 = _blogRepository.Find(1);
此时我们通过SQL Server Profiler监控得到如下SQL。

我们看到通过Find方法来查询主键等于1的数据时,声明了一个变量然后再来进行设置变量值进行查询,没毛病,上述我们是直接通过Find方法来实现,下面我们通过其他几种方法来实现。如下:
        public T GetSingle(int id)
        {            return _context.Set().FirstOrDefault(x => x.Id == id);
        } var blog = _blogRepository.GetSingle(1);

此时和上述Find方法执行的SQL无任何区别,我们先别着急下结论,我们再来通过lambda表达式来实现看看。
public T GetSingle(Expression> predicate) { return _context.Set ().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(集合类型映射支持) 
在之前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 Posts { get; set; }
    } 
我们知道在EF Core中已经不存在延迟加载这一概念,所以请用了EF Core的童鞋将virtual关键字去掉。同时我们在映射集合时一直以来都统一用的ICollection

    public class Blog : IEntityBase
    {        public int Id { get; set; }        public string Name { get; set; }        public string Url { get; set; }        public IEnumerable Posts { get; set; }
    } 
 
 
通过如上我们知道现在支持了IEnumerable
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。
- _
- _
- m_
- m_
比如属性为UserName,那么对应的Backing Fileds则依次是:_userName,_UserName,m_userName,m_UserName。配置Backing Fileds后,当从数据库查询类实例后将直接将其对应数据写到字段中,在其他时候当EF Core需要读或者写值时有可能使用属性,例如EF需要更新一个属性上的值时,此时将使用属性的set访问器,如果属性仅仅只是只读,那么将值写到字段中。例如如下配置Backing Fileds即_validateUrl。

class MyContext : DbContext
{    public DbSet Blogs { get; set; }    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity()
            .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() .Property(b => b.Url) .HasField("_validatedUrl") .UsePropertyAccessMode(PropertyAccessMode.Field); 
若我们在实体中没有属性,此时我们可以通过字段来存储数据。我们通过映射中的Porperty(...)来指定字段名称,若没有属性,此时EF Core将会查找字段,如下:

class MyContext : DbContext
{    public DbSet Blogs { get; set; }    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity()
            .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

    public class Blog : IEntityBase
    {        public int Id { get; set; }        public string Name { get; set; }        public string Url { get; set; }        public IEnumerable Posts { get; set; }
    } 
我们知道对于导航属性Posts更多的是通过Inlcude来查询出Posts,所以在这里我们完全不需要set访问器以便减少对Posts反编译为Set方法,我们完全可以改造如下:
public IEnumerablePosts { get; } = new List (); 
话又说回来了,如果我们万一需要对Post进行一些操作,那么在这种情况下该如何是好呢,此时我们通过暴露IEnumerable

    public class Blog : IEntityBase
    {        private readonly List _posts = new List();        public int Id { get; set; }        public string Name { get; set; }        public string Url { get; set; }        public IEnumerable Posts => _posts;        public void AddPost(Post post)
        {            // Do some buisness your logic             _posts.Add(post);
        }
    }   
我们实际来操作一下,查询Blog数据以及导航属性Post数据。

public virtual IEnumerableAllIncluding(params Expression >[] includeProperties) { IQueryable query = _context.Set (); 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().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()
        .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();
} 
在EF 6.x之前版本中因为导航属性的存在很容易导致循环引用,所以对于EF Core同样是如此我们需要在Startup.cs中忽略循环引用,如下:
services.AddMvc() .AddJsonOptions( options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore );
新闻标题:EntityFrameworkCore1.1有哪些新特性呢?
分享地址:http://www.cqwzjz.cn/article/giopcc.html

 建站
建站
 咨询
咨询 售后
售后
 建站咨询
建站咨询 
 