zoukankan      html  css  js  c++  java
  • EntityFramework优化:查询性能

    1. 禁用延迟加载

      延迟加载是常见的方式,Entity Framework在需要时可以自动为一个实体的实例获取关联的数据。

      Entity Framework自动延迟加载需要同时满足以下3个条件:

      (1)DbContext.Configuration.LazyLoadingEnabled = true (默认为true)

      (2)DbContext.Configuration.ProxyCreationEnabled = true (默认为true)

      (3)POCO类必须是public而非sealed,且集合属性使用Virtual修饰,这样Entity Framework才能Override以包含延迟加载。

      延迟加载示例:

    using (var ctx = new LibingContext())
    {
        var category = ctx.Categories.Find(1);
        foreach (var product in category.Products)
        {
            Console.WriteLine(product.ProductName);
        }
    }

      EntityFramework禁用延迟加载:

    public class LibingContext : DbContext
    {
        public LibingContext()
            : base("Name=LibingContext")
        {
            // 禁用延迟加载
            this.Configuration.LazyLoadingEnabled = false;
            this.Configuration.ProxyCreationEnabled = false;
        }
    }

    2. AsNoTracking()与Attach()

      对于只读操作,强烈建议使用AsNoTracking进行数据获取,降低数据获取所需的时间。

      由于没有受到DbContext的跟踪,利于对数据及时性要求高的数据查询。

      使用AsNoTracking查询出来的数据,要进行删除时,需使用Attach()。

    using (var ctx = new LibingContext())
    {
        var products = ctx.Products
            .AsNoTracking()
            .ToList();
    
        var product = products.Where(t => t.ProductID == 1).FirstOrDefault();
    
        //// 修改不用Attach
        //product.ProductName = "新名称";
        //ctx.Entry(product).State = EntityState.Modified;
    
        ctx.Set<Product>().Attach(product);
        ctx.Entry(product).State = EntityState.Deleted;
    
        ctx.SaveChanges();
    }

      注:查询过程Select映射不需要加AsNoTracking()

    var products = ctx.Products
        .Select(t => new { t.ProductID, t.ProductName })
        .ToList();

    3. AsNonUnicode

    using (var ctx = new LibingContext())
    {
        var products = ctx.Products
            .Where(t => t.ProductName == "商品")
            .ToList();
    }
    SELECT 
        [Extent1].[ProductID] AS [ProductID], 
        [Extent1].[CategoryID] AS [CategoryID], 
        [Extent1].[ProductName] AS [ProductName], 
        [Extent1].[UnitPrice] AS [UnitPrice], 
        [Extent1].[UnitsInStock] AS [UnitsInStock]
        FROM [dbo].[Product] AS [Extent1]
        WHERE N'商品' = [Extent1].[ProductName]
    using System.Data.Entity;
    using (var ctx = new LibingContext())
    {
        var products = ctx.Products
            .Where(t => t.ProductName == DbFunctions.AsNonUnicode("商品"))
            .ToList();
    }
    SELECT 
        [Extent1].[ProductID] AS [ProductID], 
        [Extent1].[CategoryID] AS [CategoryID], 
        [Extent1].[ProductName] AS [ProductName], 
        [Extent1].[UnitPrice] AS [UnitPrice], 
        [Extent1].[UnitsInStock] AS [UnitsInStock]
        FROM [dbo].[Product] AS [Extent1]
        WHERE '商品' = [Extent1].[ProductName]

      EF正常情况生成的SQL会在前面带上“N”,加上DbFunctions.AsNonUnicode生成的SQL没有“N”。“N”是将字符串作为Unicode格式进行存储。

      .Net字符串是Unicode格式,SQL中带“N”会进行数据转换,无法使用索引,只能全表扫描。

      DbFunctions.AsNonUnicode()让.Net将其作为一个非Unicode来处理。

      在进行字符串查找或者比较时建议用AsNonUnicode()方法来提高查询性能。

    4. 使用AutoMapper查询DTO

      查询需要的字段:DTO

    using AutoMapper;
    using AutoMapper.QueryableExtensions;
    using (var ctx = new LibingContext())
    {
        Mapper.Initialize(cfg => cfg.CreateMap<Product, ProductDTO>());
    
        var products = ctx.Products
            .ProjectTo<ProductDTO>()
            .ToList();
    }
  • 相关阅读:
    2014 非常好用的开源 Android 测试工具
    Android 开发最佳实践
    Java_综合案例DAO设计模式(重要)
    Java_Set接口
    Java_List
    Java_类集框架简介
    Java_对象序列化
    Java_打印流
    Java_IO编程
    Java_文件操作
  • 原文地址:https://www.cnblogs.com/libingql/p/9060653.html
Copyright © 2011-2022 走看看