[英]Entity Framework combining multiple queries into one
I have a query which it need to run 300+ loops every single call. 我有一个查询,它需要在每个调用中运行300个以上的循环。 It takes about 10 seconds to complete a call even on a new database.
即使在新数据库上,也要花费大约10秒钟才能完成通话。 It's unacceptable for a WebAPI call.
WebAPI调用是不可接受的。
var isAbnormal = false;
var list = new List<String>();
//Check date range, log them & return if there is any abnormal.
foreach (DateTime day in DateHelper.EachDay(startDate, endDate))
{
var isActive = db.Operations.Any(x=>x.IsActive && x.Day == day);
var object;
var queryable = db.ObjectA.Where(x=>x.Day == day);
if(isActive){
queryable = db.ObjectA.First(x=>x.Day == day);
LogUtil.Info($"{object.Name}");
var isLogicACorrect = queryable.Any(x=>x.ObjectACount == 5);
var isLogicBCorrect = queryable.Any(x=>x.ObjectBCount == 3);
var isLogicCCorrect = queryable.Any(x=>x.ObjectCCount == 2);
var isLogicDCorrect = queryable.Any(x=>x.ObjectDCount == 8);
var isLogicECorrect = queryable.Any(x=>x.ObjectECount == 1);
if(!isLogicACorrect){
list.Add("Logic A is incorrect");
isAbnormal = true;
}
//More logic codes & db calls here, which is just to select & validate.
}
return list;
How can I optimize the speed by combining all the queries into one? 如何通过将所有查询组合为一个来优化速度? The loop content literally the same except the day.There are total 15 queries to be call on each loop, 4500 db queries in a complete loop.
除了一天外,循环内容实际上是相同的。每个循环中总共要调用15个查询,一个完整循环中有4500个数据库查询。
Think in terms of sets and relational data and not procedurally. 根据集合和关系数据而不是程序来思考。 It's not easy to determine exactly what you want from your code (which contradicts itself -
queryable
is set by a call to db.ObjectA.Where(...)
which is an IQueryable<ObjectA>
but then it is also set by a call to db.ObjectA.First(...)
, which is an ObjectA
; I'll assume you want the IQueryable<ObjectA>
since later code references queryable.Any(...)
) but here's my guess: 从代码中准确地确定您想要的是不容易的(这与自身矛盾-
queryable
是通过对db.ObjectA.Where(...)
的调用来设置的,它是一个IQueryable<ObjectA>
但随后它也会通过调用来设置到db.ObjectA.First(...)
,这是一个ObjectA
;我假设您要使用IQueryable<ObjectA>
因为以后的代码引用了queryable.Any(...)
),但这是我的猜测:
var days = DateHelper.EachDay( startDate, endDate );
var activeDaysIsLogicCorrectFlags = db.Operations
// get days that are "active"
.Where( op => op.IsActive && days.Contains( op.Day ) )
// join with ObjectA's to filter for active ObjectA's
// is there a nav property you could use instead?
// use GroupJoin for use with `Any(...)` in results
.GroupJoin( db.ObjectA, op => op.Day, oa => oa.Day, ( op, oaGroup ) => new
{
//Operation = op,
// projecting Operation.Day since that's what your foreach loop is using
Day = op.Day,
IsLogicACorrect = oaGroup.Any( oa => oa.ObjectACount == 5 ),
// if IsLogicBCorrect can be determined from the collection of ObjectA's:
//IsLogicBCorrect = oaGroup.Any( oa => oa.ObjectBCount == 3 ),
} );
The results are an IQueryable
of an anonymous type that maps an "active" Operation.Day
with your logic for IsLogicACorrect
. 结果是一个匿名类型的
IQueryable
,该类型将您的IsLogicACorrect
逻辑映射为“活动” Operation.Day
。 For your other IsLogicXCorrect
flags, if they can all be determined using the ObjecetA
group aoGroup
, simply add them to the GroupJoin
result selector (as shown in the commented-out property). 为了您的其他
IsLogicXCorrect
标志,如果他们都可以使用确定ObjecetA
组aoGroup
,只需将它们添加到GroupJoin
结果选择(如注释掉的属性中显示)。 If those flags need their own groupings (eg need to use ObjectB
group to determine IsLogicBCorrect
, then add additional calls to GroupJoin
as shown above but using their respective DbSet
and properties. For example, if you need to use db.ObjectB
for IsLogicBCorrect
: 如果这些标志需要自己的分组(如需要使用
ObjectB
组确定IsLogicBCorrect
,再加入额外调用GroupJoin
如上,但使用各自的显示DbSet
和属性。例如,如果你需要使用。 db.ObjectB
为IsLogicBCorrect
:
var activeDaysIsLogicCorrectFlags =
<existing logic from above>
.GroupJoin( db.ObjectB, at => at.Day, ob => ob.Day, ( at, obGroup ) => new
{
// project all previous results
at.Day,
at.IsLogicACorrect,
// new flag
IsLogicBCorrecet = obGroup.Any( ob => ob.ObjectBCount == 3 ),
} );
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.