Jul*_*n50 6 c# sql linq entity
我首先使用实体代码.索引列:
表中有40 000行,
我的问题是查询需要40s !!
var result = DBContext.Set<SourceProduct>()
.Include(x => x.SalesHistories, x => x.SourceCatalog)
.Where(p => p.SourceCatalogId == 2)
.where(p => p.Disabled == false)
.where(x => x.CategoryPath.StartsWith("MyPath"))
.orderby(x => x.ShortDesignation)
.Skip(1)
.Take(10)
.toList();
Run Code Online (Sandbox Code Playgroud)
SQL通过sql profiler:
exec sp_executesql N'SELECT TOP (10)
[Project1].[SourceProductId] AS [SourceProductId],
[Project1].[SourceSKU] AS [SourceSKU],
[Project1].[SourceCatalogId] AS [SourceCatalogId],
[Project1].[ManufacturerReference] AS [ManufacturerReference],
[Project1].[Disabled] AS [Disabled],
[Project1].[EAN] AS [EAN],
[Project1].[ShortDesignation] AS [ShortDesignation],
[Project1].[FullDesignation] AS [FullDesignation],
[Project1].[Description] AS [Description],
[Project1].[Url] AS [Url],
[Project1].[CategoryPath] AS [CategoryPath],
[Project1].[Condition] AS [Condition],
[Project1].[BuyingPriceHT] AS [BuyingPriceHT],
[Project1].[ShippingPriceHT] AS [ShippingPriceHT],
[Project1].[PublicSellingPriceHT] AS [PublicSellingPriceHT],
[Project1].[PictureUrl1] AS [PictureUrl1],
[Project1].[PictureUrl2] AS [PictureUrl2],
[Project1].[PictureUrl3] AS [PictureUrl3],
[Project1].[PictureUrl4] AS [PictureUrl4],
[Project1].[Quantity] AS [Quantity],
[Project1].[AddDate] AS [AddDate],
[Project1].[UpdateDate] AS [UpdateDate],
[Project1].[Followers] AS [Followers]
FROM ( SELECT [Project1].[SourceProductId] AS [SourceProductId], [Project1].[SourceSKU] AS [SourceSKU], [Project1].[SourceCatalogId] AS [SourceCatalogId], [Project1].[ManufacturerReference] AS [ManufacturerReference], [Project1].[Disabled] AS [Disabled], [Project1].[EAN] AS [EAN], [Project1].[ShortDesignation] AS [ShortDesignation], [Project1].[FullDesignation] AS [FullDesignation], [Project1].[Description] AS [Description], [Project1].[Url] AS [Url], [Project1].[CategoryPath] AS [CategoryPath], [Project1].[Condition] AS [Condition], [Project1].[BuyingPriceHT] AS [BuyingPriceHT], [Project1].[ShippingPriceHT] AS [ShippingPriceHT], [Project1].[PublicSellingPriceHT] AS [PublicSellingPriceHT], [Project1].[PictureUrl1] AS [PictureUrl1], [Project1].[PictureUrl2] AS [PictureUrl2], [Project1].[PictureUrl3] AS [PictureUrl3], [Project1].[PictureUrl4] AS [PictureUrl4], [Project1].[Quantity] AS [Quantity], [Project1].[AddDate] AS [AddDate], [Project1].[UpdateDate] AS [UpdateDate], [Project1].[Followers] AS [Followers], row_number() OVER (ORDER BY [Project1].[ShortDesignation] ASC) AS [row_number]
FROM ( SELECT
[Extent1].[SourceProductId] AS [SourceProductId],
[Extent1].[SourceSKU] AS [SourceSKU],
[Extent1].[SourceCatalogId] AS [SourceCatalogId],
[Extent1].[ManufacturerReference] AS [ManufacturerReference],
[Extent1].[Disabled] AS [Disabled],
[Extent1].[EAN] AS [EAN],
[Extent1].[ShortDesignation] AS [ShortDesignation],
[Extent1].[FullDesignation] AS [FullDesignation],
[Extent1].[Description] AS [Description],
[Extent1].[Url] AS [Url],
[Extent1].[CategoryPath] AS [CategoryPath],
[Extent1].[Condition] AS [Condition],
[Extent1].[BuyingPriceHT] AS [BuyingPriceHT],
[Extent1].[ShippingPriceHT] AS [ShippingPriceHT],
[Extent1].[PublicSellingPriceHT] AS [PublicSellingPriceHT],
[Extent1].[PictureUrl1] AS [PictureUrl1],
[Extent1].[PictureUrl2] AS [PictureUrl2],
[Extent1].[PictureUrl3] AS [PictureUrl3],
[Extent1].[PictureUrl4] AS [PictureUrl4],
[Extent1].[Quantity] AS [Quantity],
[Extent1].[AddDate] AS [AddDate],
[Extent1].[UpdateDate] AS [UpdateDate],
[Extent1].[Followers] AS [Followers]
FROM [dbo].[SourceProducts] AS [Extent1]
WHERE ([Extent1].[SourceCatalogId] = @p__linq__0) AND (0 = [Extent1].[Disabled]) AND ([Extent1].[CategoryPath] LIKE @p__linq__1 ESCAPE N''~'')
) AS [Project1]
) AS [Project1]
WHERE [Project1].[row_number] > 0
ORDER BY [Project1].[ShortDesignation] ASC',N'@p__linq__0 bigint,@p__linq__1 nvarchar(4000)',@p__linq__0=2,@p__linq__1=N'MyPath%'
Run Code Online (Sandbox Code Playgroud)
在where子句之前的最后一个中,如果我删除" escape N''〜'' ":
WHERE ([Extent1].[SourceCatalogId] = @p__linq__0) AND (0 = [Extent1].[Disabled]) AND ([Extent1].[CategoryPath] LIKE @p__linq__1 ESCAPE N''~'')
Run Code Online (Sandbox Code Playgroud)
查询需要4s.
这是正常的吗?指数使用?我如何用startWith解决它?
编辑
categoryPath的索引属性:
[Index("IX_SourceProduct_SourceCatalogId_Disabled_CategoryPath", 3), StringLength(400)]
public string CategoryPath { get; set; }
Run Code Online (Sandbox Code Playgroud)
EDIT2
好吧,我很接近,我认为问题是存储过程.
string search = "julien";
var list = db.Users.Where(x => x.Name.StartsWith(search));
string query = list.ToString();
Run Code Online (Sandbox Code Playgroud)
=> SELECT [Extent1].[UserId] AS [UserId],[Extent1].[Name] AS [Name] FROM [dbo].[Users] AS [Extent1] WHERE [Extent1].[Name] LIKE @ p__linq__0 ESCAPE N '〜'
var list2 = db.Users.Where(x => x.Name.StartsWith("julien"));
string query2 = list2.ToString();
Run Code Online (Sandbox Code Playgroud)
=> SELECT [Extent1].[UserId] AS [UserId],[Extent1].[Name] AS [Name] FROM [dbo].[Users] AS [Extent1] WHERE [Extent1].[Name] LIKE N'julien %"
所以如果我在查询中使用变量来获取存储过程,如果我使用const我得到select.
在存储过程中(由实体生成)使得出现@ p__linq__0因此添加ESCAPE N'〜'以避免变量中的wildCaractere.
所以现在问题更简单了.如何避免变量查询?这是可能的 ?谢谢
所以你需要做的是获取变量的值并将其用作生成的常量Expression.这实际上是非常有可能的.我们需要的是一个表达式,它接受你想要的参数作为真实选择器的参数,作为第二个参数,它是常量值的占位符,然后是你想要成为常量的值.然后我们可以用常量的值替换参数的所有实例,只留下一个将真实参数映射到结果的函数:
public static Expression<Func<TSource, TResult>> EmbedConstant
<TSource, TResult, TConstant>(
this Expression<Func<TSource, TConstant, TResult>> expression,
TConstant constant)
{
var body = expression.Body.Replace(
expression.Parameters[1],
Expression.Constant(constant));
return Expression.Lambda<Func<TSource, TResult>>(
body, expression.Parameters[0]);
}
Run Code Online (Sandbox Code Playgroud)
这依赖于以下方法将一个表达式的所有实例替换为另一个:
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
Run Code Online (Sandbox Code Playgroud)
这允许您映射:
string search = "julien";
var list = db.Users.Where(x => x.Name.StartsWith(search));
string query = list.ToString();
Run Code Online (Sandbox Code Playgroud)
进入:
string search = "julien";
Expression<Func<User, string, bool>> predicate =
(item, searchTerm) => item.Name.StartsWith(searchTerm);
var list = db.Users.Where(predicate.EmbedConstant(search));
string query = list.ToString();
Run Code Online (Sandbox Code Playgroud)