简体   繁体   English

如何仅依赖 C#/LINQ 在 Entity Framework 中创建和使用临时表

[英]How to create and use temp table in Entity Framework relying only on C#/LINQ

Entity Framework is my first choice of O/RMs.实体框架是我的 O/RM 的首选。 We can write our queries against DB using C#/LINQ.我们可以使用 C#/LINQ 编写针对 DB 的查询。 We can even create our model in C# and easily migrate it into DB.我们甚至可以在 C# 中创建我们的模型并轻松地将其迁移到 DB。 No custom data access-code, no mixing data-access code with a huge SQL string, ...没有自定义数据访问代码,没有将数据访问代码与巨大的 SQL 字符串混合,......

However, sometimes I was faced against bad performances due to bad query generated by Entity Framework, including an error like但是,有时由于 Entity Framework 生成的错误查询,我会遇到糟糕的性能,包括像这样的错误

The query processor ran out of internal resources and could not produce a query plan.查询处理器耗尽了内部资源,无法生成查询计划。 This is a rare event and only expected for extremely complex queries or queries that reference a very large number of tables or partitions.这是一种罕见的事件,仅适用于极其复杂的查询或引用大量表或分区的查询。 Please simplify the query.请简化查询。

Suggestions like here are helpful, but we are limited as we can't create temp table entities in Entity Framework context.这里这样的建议很有帮助,但我们受到限制,因为我们无法在 Entity Framework 上下文中创建临时表实体。

So, I started asking myself how to introduce temp tables in Entity Framework?所以,我开始问自己如何在实体框架中引入临时表?

Is there any easy way to do this?有什么简单的方法可以做到这一点吗?

Of course, there is a way to introduce temporary tables in Entity Framework context.当然,有一种方法可以在 Entity Framework 上下文中引入临时表。

But, before I started explaining how to use temp tables in Entity Framework context I want to explain what was my goal in order to achieve such a feature.但是,在我开始解释如何在 Entity Framework 上下文中使用临时表之前,我想解释一下我实现这样一个功能的目标是什么。

So, let's start...那么,让我们开始吧……

My goal was to add an entity that represents temp table from DB and write a LINQ query to load the data into it.我的目标是添加一个代表 DB 中临时表的实体,并编写一个 LINQ 查询以将数据加载到其中。 Later on, in code, I wanted to use it in LINQ as I'm using any other entity that represents a permanent table.后来,在代码中,我想在 LINQ 中使用它,因为我正在使用代表永久表的任何其他实体。

Seems like steps to achieve it are very straightforward looking from T-SQL perspective:从 T-SQL 的角度来看,实现它的步骤似乎非常简单:

  1. create a temp table创建临时表
  2. load the data into it将数据加载到其中
  3. use it later in the code稍后在代码中使用它

but from C# it's not so trivial because I had to find out:但从 C# 来看并不是那么简单,因为我必须找出:

  1. how to get translated from LINQ T-SQL query with all the parameters如何使用所有参数从 LINQ T-SQL 查询转换
  2. how to declare entity that represents temp table in DB and distinguish it from other entities如何在数据库中声明表示临时表的实体并将其与其他实体区分开来
  3. how to load data into temp entity如何将数据加载到临时实体中
  4. how to get parameter order from LINQ query being used to load the data into temp table如何从用于将数据加载到临时表的 LINQ 查询中获取参数顺序
  5. how to handle dependencies between temp tables如何处理临时表之间的依赖关系
  6. how to attach prepared "temp query" into DbContext如何将准备好的“临时查询”附加到 DbContext
  7. .... ....

Anyway, after some digging through the Entity Framework 6 source code and searching on the Internet I found what do I need and, finally, I've got proof and concept followed by the first version.无论如何,在对 Entity Framework 6 源代码进行一些挖掘并在 Internet 上搜索之后,我找到了我需要什么,最后,我得到了第一个版本后面的证明和概念。

Here is a very simple usage:这是一个非常简单的用法:

  1. declare a temp entity声明一个临时实体

    [Table("#tempAddress")] public class AddressTempTable : ITempTable { [Key] [TempFieldTypeAttribute("int")] public int AddressId { get; set; } [TempFieldTypeAttribute("varchar(200)")] public string StreetName { get; set; } }
  2. add an entity that represents temp table in DbSet collection在 DbSet 集合中添加一个代表临时表的实体

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

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

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

I published my solution in a form of Nuget package called - EF6TempTableKit .我以一种名为 - EF6TempTableKit的 Nuget 包形式发布了我的解决方案。

Here is a very basic example .这是一个非常基本的例子

Source code is available here .源代码可在此处获得

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM