我正在使用C#和Entity Framework与SQL Server数据库进行通信,其中我有2个表,我需要信息来自。第一个表(维度表)代表某些计数器,并保存信息,例如:计数器ID(主键),计数器类型,与之相关的机器。第二个表(事实表)保存计数器数据,如数据ID(主键),计数器ID(外键,维度表的链接),日期和值。
我使用Entity Framework来处理这些表,我使用Visual Studio的工具将它们连接在一起。我在Visual Studio中设计了它,因此可以从计数器数据类中获取计数器类型的详细信息 - CounterData.CounterDetail.CounterType
。实体框架负责这种加入(至少我希望如此)。
现在,作为输入,我得到机器名称和计数器类型。我需要打印特定计数器类型(维度)的所有计数器数据(所有事实)。我写了这种代码(假设db是我的Entity Framework对象):
db.CounterDatas.Where(x => (x.CounterDetail.MachineID == input_machine) &&
input_counter_types.Contains(x.CounterDetail.CounterType)).Select(x => x).GroupBy(x => x.CounterDetail);
然后我使用foreach迭代组,我也迭代每个组。 然而,这非常缓慢。数据库表是庞大的(事实表超过4000万行),但手动执行我自己编写的SQL查询会在瞬间执行。但实体框架的速度非常慢。
起初,我认为
input_counter_types.Contains(x.CounterDetail.CounterType)
部分减慢了很多,但在看了智能感知报告的SQL查询后,实体框架实际上将input_counter_types
部分扩展为类似
CounterType IN ('A', 'B', 'C', ...)
其中A,B,C,...是存储在哈希集input_counter_types
中的常量,并且应该在没有问题的情况下快速执行,对吗?
我还在Stack Overflow上的某处读到,这些LINQ查询的问题有时是LINQ将太多行(远远超过需要的行)加载到本地内存中,然后在本地过滤数据。这是不受欢迎的行为,我希望SQL Server能够进行过滤工作,我只想在本地过滤数据。
有可能吗?我将在项目的不同部分(具有不同的复杂性)中使用类似的代码,我更喜欢让Entity Framework完成所有数据库工作。也许这不是最好的决定?
答案 0 :(得分:0)
问题已经解决了。
对于任何想要了解的人,我通过翻转我的选择逻辑来解决它。
我没有使用Where
和x.CounterDetail
- 使用表达式,而是使用Where
和x.CounterDatas
- 在选择详细实体时使用表达式,而不是数据实体。最后,我做了同样的事情(虽然没有GroupBy
),但它显着加快了一切。