这里的想法。我有一个简单的表,模型首先与Entity Framework映射,我得到以下SQL生成:
(@p__linq__0 int,@p__linq__1 int)SELECT
[Extent1].[BucketRef] AS [BucketRef],
[Extent1].[VariantNo] AS [VariantNo],
[Extent1].[SliceNo] AS [SliceNo],
[Extent1].[TradeNo] AS [TradeNo],
[Extent1].[TradeBegin] AS [TradeBegin],
[Extent1].[TradeEnd] AS [TradeEnd],
FROM [simstg].[Trade] AS [Extent1]
WHERE ((( CAST( [Extent1].[BucketRef] AS int) = @p__linq__0) AND ( NOT (( CAST( [Extent1].[BucketRef] AS int) IS NULL) OR (@p__linq__0 IS NULL)))) OR (( CAST( [Extent1].[BucketRef] AS int) IS NULL) AND (@p__linq__0 IS NULL))) AND ((( CAST( [Extent1].[VariantNo] AS int) = @p__linq__1) AND ( NOT (( CAST( [Extent1].[VariantNo] AS int) IS NULL) OR (@p__linq__1 IS NULL)))) OR (( CAST( [Extent1].[VariantNo] AS int) IS NULL) AND (@p__linq__1 IS NULL)))
所有演员都会杀死他们。我很遗憾没有看到他们来自哪里。
有问题的查询是:
var tradesQuery = repository.SimStgTrade
.Where(x => x.BucketRef == bucketId && x.VariantNo == set)
.ToArray();
这很简单。字段定义为:bucketId:short(数据库中为smallint),设置为short,smallint为数据库。因此,完全不需要演员表。我已经删除并重新创建了模型中的表 - 据我所知,映射匹配(字段为smallint)。因此,我们遇到了严重的性能问题 - 例如:查询超时,因为它不使用表扫描。
任何人都知道如何摆脱那些演员并迫使比较基于短裤?从SQL中可以看出,EF决定首先将所有内容移动到一个int ......这没有任何意义。
这不是“很好”的事情。优秀的查询路径完全不同,结果代码将其转换为自连接。在服务器管理器中,EF变体需要超过5分钟,而带有简单SQL的优化版本需要0.0秒(在该表中返回数十亿的228行)。
答案 0 :(得分:16)
这种行为对于不同的LINQ提供程序来说很常见,而且不仅仅是EF特定的,因为C#编译器如何为Where表达式生成表达式树。
将条件指定为:
.Where(x => x.BucketRef == bucketId)
并且BucketRef和bucketId都是short,编译器为两个比较部分生成从short到int的转换,因为== operator没有为Short类型定义。这在答案https://stackoverflow.com/a/18584429/869184
中有解释作为一种解决方法,您可以通过以下方式重写条件:
.Where(x => x.BucketRef.Equals(bucketId))
这有效地从比较中删除了演员。
答案 1 :(得分:2)
您需要使用Expression类中的静态函数自己创建Where
表达式。
像这样:
Int16 bucketId = 3;
var parameter = Expression.Parameter(typeof(SimStgTrade));
var property = Expression.PropertyOrField(parameter, "BucketRef");
var constant = Expression.Constant(bucketId);
var comparison = Expression.Equal(property, constant);
var lambda = Expression.Lambda<Func<SimStgTrade,bool>>(comparison, parameter);
var tradesQuery = repository.SimStgTrade
.Where(lambda)
.Where(x => x.VariantNo == set)
.ToArray();
对VariantNo == set
执行同样的操作以删除该演员表