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();
    }
  • 相关阅读:
    015.Delphi插件之QPlugins,FMX插件窗口
    014.Delphi插件之QPlugins,MDI窗口
    013.Delphi插件之QPlugins,模块化代码示例
    012.Delphi插件之QPlugins,多实例内嵌窗口服务
    011.Delphi插件之QPlugins,延时加载服务
    010.Delphi插件之QPlugins,遍历服务接口
    009.Delphi插件之QPlugins,服务的热插拔
    008.Delphi插件之QPlugins,服务的两种调用方法
    007.Delphi插件之QPlugins,插件的卸载和重新加载
    006.Delphi插件之QPlugins,多服务演示
  • 原文地址:https://www.cnblogs.com/libingql/p/9060653.html
Copyright © 2011-2022 走看看