Erk*_*rel 7 c# sql-server linq-to-entities entity-framework azure-sql-database
首先我尝试ARITHABORT OFF了SSMS,但仍然不到1秒.
我使用EntityFrameWork:6.1.3和Azure Sql S1层(我将尝试使用第3层,让你知道是否有变化.)
我使用EF Profiler从linq获取生成的sql.我已经查询过我所分享的所有linq,它们在SSMS上都不到1秒.
我在AuditLog Table上有300万个recods.ID 3的一个客户有170K记录,ID 35的另一个客户有125个记录.我会尽量减少代码.
AuditLog模型:
public class AuditLog
{
public long? CustomerId { get; set; }
[ForeignKey("CustomerId")]
public virtual CustomerSummary Customer { get; set; }
[Required]
[Index]
public DateTime CreatedDate { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
第一个查询:
if (customer != null)
{
var customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).ToList();
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试拥有170k行的客户,它会给出超时的例外.如果我尝试拥有125条记录的客户,那很好.
第二个查询:与第一个查询相同,我只包括客户.
if (customer != null)
{
var customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).Include(x => x.Customer).ToList();
}
Run Code Online (Sandbox Code Playgroud)
结果与第一个查询相反.如果我尝试拥有170k行的客户,那很好.如果我尝试拥有125条记录的客户,则会给出超时异常.
第三个查询:与第一个查询相同,但我匹配long?customerId的位置.
if (customer != null)
{
long? customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).ToList();
}
Run Code Online (Sandbox Code Playgroud)
结果与第一个查询相反.如果我尝试拥有170k行的客户,那很好.如果我尝试拥有125条记录的客户,则会给出超时异常.
第四个查询:它与第二个查询相同,但我匹配long?customerId的位置.
if (customer != null)
{
long? customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).Include(x => x.Customer).ToList();
}
Run Code Online (Sandbox Code Playgroud)
结果与第二个查询相反.如果我尝试拥有170k行的客户,它会给出超时的例外.如果我尝试拥有125条记录的客户,那很好.
我真的很困惑.为什么内部联接或更改匹配参数long?会改变结果?为什么所有查询在SSMS上运行不到1秒并且在ef linq上出错?
错误:
{System.Data.SqlClient.SqlException(0x80131904):超时已过期.操作完成之前经过的超时时间或服务器没有响应.---> System.ComponentModel.Win32Exception(0x80004005):等待操作在System.Data.SqlClient.SqlConnection.OnError超时(SqlException异常,Boolean breakConnection,Action`1 wrapCloseInAction)
更新(2016年4月19日):
在Ivan Stoev就意见提出建议之后.
您是否尝试过(仅仅为了测试)使用硬编码的3和35而不是
customerId变量?
我没有收到任何错误,查询速度最快,就像在SSMS上一样.
更新(2016年4月20日):真正的问题是参数嗅探.当我将参数包含或更改为可空时,实际上我已经创建了另一个查询和另一个查询计划.我创建了一些计划,其客户拥有125条记录,而其他客户的客户拥有这4条查询的170k记录.这就是我得到不同结果的原因.
您遇到的是所谓的“ 参数嗅探问题”的结果。到目前为止,我还不知道一个简单的通用解决方案,因此通常建议一种解决方法,即通过在表达式内部手动绑定常量值来消除一些SQL查询参数,例如在EntityFramework LINQ中查询失败,但是查询返回结果。如何优化LINQ查询?。
对于您的方案,我建议使用以下自定义扩展方法:
public static class QueryableExtensions
{
public static IQueryable<T> WhereEquals<T, TValue>(this IQueryable<T> source, Expression<Func<T, TValue>> selector, TValue value)
{
var predicate = Expression.Lambda<Func<T, bool>>(
Expression.Equal(selector.Body, Expression.Constant(value)),
selector.Parameters);
return source.Where(predicate);
}
}
Run Code Online (Sandbox Code Playgroud)
然后像这样更新您的代码段
if (customer != null)
{
var result= Dbset.WhereEquals(x => x.CustomerId.Value, customer.Id)
.OrderByDescending(x => x.CreatedDate)
.Skip(0).Take(25)
.Include(x => x.Customer)
.ToList();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1155 次 |
| 最近记录: |