Lor*_*nzo 9 c# linq-to-entities entity-framework asp.net-mvc-5
您好我正在使用MVC 5和Entity Framework 6我的项目.我有一个如下图所示的模型:
我需要从一组Tag对象开始查询实体产品.请注意,Tagobject是一个抽象类,实际上是使用Table-Per-Entity策略继承映射的.
这是我的函数方法的签名
public IEnumerable<Product> SerachByTag( IEnumerable<Tag> tagList );
Run Code Online (Sandbox Code Playgroud)
在tagList参数中实际上会有具体的Tag实现实例.
我该如何进行此查询?
例如,我可以在输入中接收以下数据结构
[
{ tagType: 1, stringProperty: "abc" },
{ tagType: 2, intProperty: 9 }
]
Run Code Online (Sandbox Code Playgroud)
等等.哪种过滤产品更好?例如,我当然可以首先为每个标准应用产品列表,然后将这些结果交叉,如下例所示:
var p1 = ctx.Tags
.OfType<FirstTagType>()
.Where( x => x.StringProperty.Equals("abc") )
.Select( x => x.Products );
var p2 = ctx.Tags
.OfType<SecondTagType>()
.Where( x => x.IntProperty == 9 )
.Select( x => x.Products );
var results = p1.Intersect( p2 );
Run Code Online (Sandbox Code Playgroud)
但我在这个案例中的问题是关于表演.此查询如何与许多过滤器一起使用?
如果您查看生成的SQL查询,您会发现类似的东西:
SELECT
[Intersect1].[ProductId] AS [C1],
[Intersect1].[ProductName] AS [C2]
FROM (SELECT
[Extent3].[ProductId] AS [ProductId],
[Extent3].[ProductName] AS [ProductName]
FROM [dbo].[FirstTag] AS [Extent1]
INNER JOIN [dbo].[Tag] AS [Extent2] ON [Extent1].[TagId] = [Extent2].[TagId]
LEFT OUTER JOIN [dbo].[Product] AS [Extent3] ON [Extent2].[Product_ProductId] = [Extent3].[ProductId]
WHERE N'aaaa-9' = [Extent1].[StringProperty]
INTERSECT
SELECT
[Extent6].[ProductId] AS [ProductId],
[Extent6].[ProductName] AS [ProductName]
FROM [dbo].[SecondTag] AS [Extent4]
INNER JOIN [dbo].[Tag] AS [Extent5] ON [Extent4].[TagId] = [Extent5].[TagId]
LEFT OUTER JOIN [dbo].[Product] AS [Extent6] ON [Extent5].[Product_ProductId] = [Extent6].[ProductId]
WHERE -9 = [Extent4].[IntProperty]) AS [Intersect1]
Run Code Online (Sandbox Code Playgroud)
在这里,您可以看到内部选择查询正在完成您期望的操作.连接基于外键,并且应该快速使用列上的索引.因此,如果您有许多过滤器,则只需确保它们都在正确编制索引的列上.
LINQ Intersect被转换为SQL INTERSECT,它适用于"product"表的所有列.您可能想要查看您身边的实际执行计划,这可能取决于很多事情.
在我看来,我看到的是SQL Server执行第一个查询,然后在结果上调用"Distinct Sort",然后做实际的交叉,它执行"左半连接" ProductId和ProductName(所以全部) Product表中的列).这可能不是最好的,因为我的猜测是你没有所有列的索引.
优化此方法的一种方法是仅在主键上进行交叉(应该很快),然后根据ID获取所有产品数据:
var p1 = ctx.Tags
.OfType<FirstTag>()
.Where(x => x.StringProperty.Equals("aaaa-9"))
.Select(x => x.Product.ProductId);
var p2 = ctx.Tags
.OfType<SecondTag>()
.Where(x => x.IntProperty == -9)
.Select(x => x.Product.ProductId);
var query = ctx.Products.Where(p => p1.Intersect(p2).Contains(p.ProductId));
Run Code Online (Sandbox Code Playgroud)
生成的基础SQL查询使用,EXISTS并且其执行计划使用内部联接(在主键上).
但是,如果没有首先检查是否存在性能问题,我实际上不会启动此优化过程.
| 归档时间: |
|
| 查看次数: |
160 次 |
| 最近记录: |