运行 linq 查询时 DbContext 超时
DbContext timeout while running linq query
我有以下异步方法查询数据库中的一些数据。
private async Task<List<MyObject>> GetTotalConcert(DateTime d1, DateTime d2, string[] name)
{
using (RegistrationDbContext context = new RegistrationDbContext())
{
IQueryable<MyObject> results;
results = (from t1 in context.Table1
join t2 in context.Table2 on t1.Id equals t2.Id
where (t2.CreatedOn >= d1 && t2.CreatedOn < d2)
&& (name.Contains(t2.Name))
&& t1.EventName.Equals("Concert")
select new MyObject
{
Id = t2.Id,
EventName = t1.EventName,
Status = t2.Status,
ProjectName = t2.Name
});
return await results.Distinct().ToAsyncEnumerable().ToList();
}
}
此代码在日期范围太宽的情况下失败并出现超时异常。我试图通过这样做来增加超时:
public class RegistrationDbContext : DbContext
{
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
base.Database.SetCommandTimeout(300);
}
// Some more code here....
}
我这里有什么地方做错了吗?如果我 运行 对数据库本身的 SQL 查询,对于相同的日期范围,它需要将近 18 秒...
我正在使用 ASP.NET 5 MVC6 和 EF7。
对于这些时间范围太宽并且数据库需要更多时间 return 数据的情况,我如何摆脱超时异常?
这个问题很可能与所谓的 Parameter Sniffing Problem, similar to 有关。
您可以从 link:
获取助手 class 的修改版本
using System;
using System.Linq;
using System.Linq.Expressions;
public static class QueryableUtils
{
public static IQueryable<T> WhereIn<T>(this IQueryable<T> source, Expression<Func<T, DateTime>> dateSelector, DateTime startDate, DateTime endDate)
{
var startCond = Expression.GreaterThanOrEqual(dateSelector.Body, Expression.Constant(startDate));
var endCond = Expression.LessThan(dateSelector.Body, Expression.Constant(endDate));
var predicate = Expression.Lambda<Func<T, bool>>(Expression.AndAlso(startCond, endCond), dateSelector.Parameters[0]);
return source.Where(predicate);
}
public static IQueryable<T> WhereIn<T>(this IQueryable<T> source, Expression<Func<T, DateTime?>> dateSelector, DateTime startDate, DateTime endDate)
{
var startCond = Expression.GreaterThanOrEqual(dateSelector.Body, Expression.Constant(startDate, typeof(DateTime?)));
var endCond = Expression.LessThan(dateSelector.Body, Expression.Constant(endDate, typeof(DateTime?)));
var predicate = Expression.Lambda<Func<T, bool>>(Expression.AndAlso(startCond, endCond), dateSelector.Parameters[0]);
return source.Where(predicate);
}
}
然后将您的查询更改为:
results = (from t1 in context.Table1
join t2 in context.Table2.WhereIn(x => x.CreatedOn, d1, d2) on t1.Id equals t2.Id
where (name.Contains(t2.Name))
&& t1.EventName.Equals("Concert")
select new MyObject
{
Id = t2.Id,
EventName = t1.EventName,
Status = t2.Status,
ProjectName = t2.Name
});
看看是否有帮助。
我有以下异步方法查询数据库中的一些数据。
private async Task<List<MyObject>> GetTotalConcert(DateTime d1, DateTime d2, string[] name)
{
using (RegistrationDbContext context = new RegistrationDbContext())
{
IQueryable<MyObject> results;
results = (from t1 in context.Table1
join t2 in context.Table2 on t1.Id equals t2.Id
where (t2.CreatedOn >= d1 && t2.CreatedOn < d2)
&& (name.Contains(t2.Name))
&& t1.EventName.Equals("Concert")
select new MyObject
{
Id = t2.Id,
EventName = t1.EventName,
Status = t2.Status,
ProjectName = t2.Name
});
return await results.Distinct().ToAsyncEnumerable().ToList();
}
}
此代码在日期范围太宽的情况下失败并出现超时异常。我试图通过这样做来增加超时:
public class RegistrationDbContext : DbContext
{
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
base.Database.SetCommandTimeout(300);
}
// Some more code here....
}
我这里有什么地方做错了吗?如果我 运行 对数据库本身的 SQL 查询,对于相同的日期范围,它需要将近 18 秒...
我正在使用 ASP.NET 5 MVC6 和 EF7。
对于这些时间范围太宽并且数据库需要更多时间 return 数据的情况,我如何摆脱超时异常?
这个问题很可能与所谓的 Parameter Sniffing Problem, similar to
您可以从 link:
获取助手 class 的修改版本using System;
using System.Linq;
using System.Linq.Expressions;
public static class QueryableUtils
{
public static IQueryable<T> WhereIn<T>(this IQueryable<T> source, Expression<Func<T, DateTime>> dateSelector, DateTime startDate, DateTime endDate)
{
var startCond = Expression.GreaterThanOrEqual(dateSelector.Body, Expression.Constant(startDate));
var endCond = Expression.LessThan(dateSelector.Body, Expression.Constant(endDate));
var predicate = Expression.Lambda<Func<T, bool>>(Expression.AndAlso(startCond, endCond), dateSelector.Parameters[0]);
return source.Where(predicate);
}
public static IQueryable<T> WhereIn<T>(this IQueryable<T> source, Expression<Func<T, DateTime?>> dateSelector, DateTime startDate, DateTime endDate)
{
var startCond = Expression.GreaterThanOrEqual(dateSelector.Body, Expression.Constant(startDate, typeof(DateTime?)));
var endCond = Expression.LessThan(dateSelector.Body, Expression.Constant(endDate, typeof(DateTime?)));
var predicate = Expression.Lambda<Func<T, bool>>(Expression.AndAlso(startCond, endCond), dateSelector.Parameters[0]);
return source.Where(predicate);
}
}
然后将您的查询更改为:
results = (from t1 in context.Table1
join t2 in context.Table2.WhereIn(x => x.CreatedOn, d1, d2) on t1.Id equals t2.Id
where (name.Contains(t2.Name))
&& t1.EventName.Equals("Concert")
select new MyObject
{
Id = t2.Id,
EventName = t1.EventName,
Status = t2.Status,
ProjectName = t2.Name
});
看看是否有帮助。