首页 > 解决方案 > 如何在仅依赖 C#/LINQ 的实体框架中创建和使用临时表

问题描述

Entity Framework 是我首选的 O/RM。我们可以使用 C#/LINQ 编写针对 DB 的查询。我们甚至可以在 C# 中创建我们的模型并轻松地将其迁移到数据库中。没有自定义数据访问代码,没有将数据访问代码与巨大的 SQL 字符串混合,......

但是,有时我会因为 Entity Framework 生成的错误查询而面临糟糕的性能,包括类似的错误

查询处理器用尽了内部资源,无法生成查询计划。这是一个罕见的事件,仅适用于极其复杂的查询或引用大量表或分区的查询。请简化查询。

这里这样的建议很有帮助,但我们受到限制,因为我们无法在实体框架上下文中创建临时表实体。

所以,我开始问自己如何在 Entity Framework 中引入临时表?

有什么简单的方法可以做到这一点?

标签: c#entity-framework

解决方案


当然,有一种方法可以在 Entity Framework 上下文中引入临时表。

但是,在我开始解释如何在 Entity Framework 上下文中使用临时表之前,我想解释一下我的目标是什么,以实现这样的功能。

那么,让我们开始...

我的目标是从 DB 添加一个表示临时表的实体并编写一个 LINQ 查询以将数据加载到其中。后来,在代码中,我想在 LINQ 中使用它,因为我正在使用任何其他表示永久表的实体。

从 T-SQL 的角度来看,实现它的步骤似乎非常简单:

  1. 创建临时表
  2. 将数据加载到其中
  3. 稍后在代码中使用它

但从 C# 开始,这并不是那么简单,因为我必须找出:

  1. 如何使用所有参数从 LINQ T-SQL 查询中进行翻译
  2. 如何在数据库中声明代表临时表的实体并将其与其他实体区分开来
  3. 如何将数据加载到临时实体中
  4. 如何从用于将数据加载到临时表中的 LINQ 查询中获取参数顺序
  5. 如何处理临时表之间的依赖关系
  6. 如何将准备好的“临时查询”附加到 DbContext
  7. ……

无论如何,经过一番挖掘 Entity Framework 6 源代码并在 Internet 上搜索,我找到了我需要的东西,最后,我得到了第一个版本的证明和概念。

这是一个非常简单的用法:

  1. 声明一个临时实体

    [Table("#tempAddress")]
    public class AddressTempTable : ITempTable
    {
        [Key]
        [TempFieldTypeAttribute("int")]
        public int AddressId { get; set; }
    
        [TempFieldTypeAttribute("varchar(200)")]
        public string StreetName { get; set; }
    }
    
  2. 在 DbSet 集合中添加一个表示临时表的实体

    public DbSet<AddressTempTable> AddressesTempTable { get; set; }
    
  3. 将数据加载到其中

    var tempAddressQuery = entityContext.Addresses.Select(a => new AddressTempTableDto { AddressId = a.AddressId , StreetName = a.StreetName });
    
  4. 附加并使用它

    var addressList = entityContext
       .WithTempTableExpression<EntityContext>(tempAddressQuery)
       .AddressesTempTable.Join(entityContext.Addresses,
       (a) => a.AddressId,
       (aa) => aa.AddressId,
       (at, a) => new 
       {
            AddressId = at.AddressId,
            StreetName = a.StreetName
        }).ToList();
    

我以一种名为 - EF6TempTableKit的 Nuget 包的形式发布了我的解决方案。

这是一个非常基本的例子

源代码可在此处获得。


推荐阅读