如何在仅依赖C#/LINQ的实体框架中创建和使用临时表

如何在仅依赖C#/LINQ的实体框架中创建和使用临时表,c#,entity-framework,C#,Entity Framework,实体框架是我首选的O/RMs。我们可以使用C#/LINQ编写针对DB的查询。我们甚至可以在C#中创建模型,并轻松地将其迁移到DB中。没有自定义数据访问代码,也没有将数据访问代码与庞大的SQL字符串混合使用 然而,有时我会遇到由于实体框架生成的错误查询而导致的不良性能,包括以下错误 查询处理器耗尽了内部资源,无法生成查询计划。这是一个罕见的事件,仅适用于非常复杂的查询或引用大量表或分区的查询。请简化查询 像这样的建议很有用,但我们受到限制,因为我们无法在实体框架上下文中创建临时表实体 所以,我开始

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

然而,有时我会遇到由于实体框架生成的错误查询而导致的不良性能,包括以下错误

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

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

所以,我开始问自己如何在实体框架中引入临时表


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

当然,有一种方法可以在实体框架上下文中引入临时表

但是,在我开始解释如何在实体框架上下文中使用临时表之前,我想解释一下,为了实现这样一个特性,我的目标是什么

那么,让我们开始

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

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

  • 创建临时表
  • 将数据加载到其中
  • 稍后在代码中使用它
  • 但从C#看来,这并不是那么简单,因为我必须找出:

  • 如何使用所有参数从LINQ T-SQL查询中进行转换
  • 如何声明在数据库中表示临时表的实体,并将其与其他实体区分开来
  • 如何将数据加载到临时实体中
  • 如何从用于将数据加载到临时表的LINQ查询中获取参数顺序
  • 如何处理临时表之间的依赖关系
  • 如何将准备好的“临时查询”附加到DbContext中
  • 无论如何,在深入挖掘Entity Framework 6源代码并在互联网上搜索之后,我找到了我需要的东西,最后,我得到了第一个版本的证明和概念

    下面是一个非常简单的用法:

  • 声明一个临时实体

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

    public DbSet<AddressTempTable> AddressesTempTable { get; set; }
    
  • 附加并使用它

    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();
    
    var addressList=entityContext
    .WithTestableExpression(tempAddressQuery)
    .AddressesTempTable.Join(entityContext.Addresses,
    (a) =>a.AddressId,
    (aa)=>aa.AddressId,
    (at,a)=>新建
    {
    AddressId=at.AddressId,
    StreetName=a.StreetName
    }).ToList();
    
  • 我以名为-,的Nuget包的形式发布了我的解决方案

    这是一个非常基本的问题

    源代码可用

    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();