问题,同时过滤日期范围内的记录&使用LINQ匹配CityID时,查询在分2步写入时成功;但是,在组合成一个查询时失败了!
如何重写LINQ查询,以便 - 它可以执行两个过滤器(即匹配Unhandled rejection ValidationError: College validation failed
at new ValidationError (C:\MyProject\node_modules\mongoose\lib\error\validation.js:23:11)
at model.Document.invalidate (C:\MyProject\node_modules\mongoose\lib\document.js:1629:32)
at C:\MyProject\node_modules\mongoose\lib\document.js:1501:17
at validate (C:\MyProject\node_modules\mongoose\lib\schematype.js:733:7)
at C:\MyProject\node_modules\mongoose\lib\schematype.js:778:11
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (C:\MyProject\node_modules\mongoose\lib\schematype.js:738:19)
at C:\MyProject\node_modules\mongoose\lib\document.js:1499:9
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
并检索{{1}中的记录1}} 同一步以提高效果?
我让它分两步完成,
即。做一个
CityId
然后
date range
当我把它们组合起来时它失败了!!
var Step1 = db.weekRecord.Where(x => x.CityId == CityRecord.Id).ToList();
在查找其他SO answers之后,我尝试了这个 TruncateTime ...无法让它工作..
Step1.Where(x => x.date.Date >= fromDate.Date
&& x.date.Date <= toDate.Date)
.ToList();
错误:
[NotSupportedException:指定的类型成员'Date'不是 LINQ to Entities支持。只有初始化者,实体成员和 支持实体导航属性。]
System.Data.Entity.Core.Objects.ELinq.MemberAccessTranslator.TypedTranslate(ExpressionConverter parent,MemberExpression linq)+452
System.Data.Entity.Core.Objects.ELinq.TypedTranslator`1.Translate(ExpressionConverter parent,Expression linq)+49
答案 0 :(得分:1)
问题很混乱,但我认为问题是.Date
。与linq2sql不同,实体框架无法将.Date
转换为sql。但你可以像
var fromDateDate = fromDate.Date;
var toDateDate = toDate.Date;
var testQueryRecrods = db.weekRecord
.Where(x => x.CityId == CityRecord.Id)
.Where(x => DbFunctions.TruncateTime(x.date) >= fromDateDate
&& DbFunctions.TruncateTime(x.date) <= toDateDate)
.ToList();
它会起作用。到某一点。在这种情况下,EF产生的实际上是完全愚蠢的。与linq2sql不同,EF生成查询,这不是sargable(在我的情况下*)。它可以比必要的慢几千倍。我建议完全避免转换到日期:
var fromDateDate = fromDate.Date;
var toDateDate1 = toDate.Date.AddDays(1);
var testQueryRecrods = db.weekRecord
.Where(x => x.CityId == CityRecord.Id)
.Where(x => x.date >= fromDateDate
&& x.date < toDateDate1)
.ToList();
正如@juharr指出的那样,当你拆分查询时,你会在服务器上运行前半部分,而后半部分作为对象的linq运行。在这种情况下.Date
可以正常工作,但是你在上半部分下载的记录比你需要的多得多。
*日期时间类型可能是问题,也许它会更好用datetime2,我没有测试这个场景
答案 1 :(得分:0)
最好的建议是为此编写自己的LINQ扩展..
public static class ext
{
//This extension compares one date to another... if you can call from Linq
public static bool GreaterThan(this DateTime self, DateTime CompareDate
{
if (self.Year > CompareDate.Year) return true;
else if ((self.Year == CompareDate.Year) && (self.Month > CompareDate.Month)
return true;
else if ((self.Year == CompareDate.Year) && (self.Month == CompareDate.Month) && (self.Day > CompareDate.Day))
return true;
return false;
}
}
答案 2 :(得分:0)
我认为除了使用DbFunctions.TruncateTime
Linq to Entities之外别无选择。因为,SQL Server查询Linq to Entities应执行转换datetime
到date
,并且可以使用的最佳方法是DbFunctions.TruncateTime
。我刚调试DbFunctions.TruncateTime
转换,翻译的查询似乎是;
WHERE (convert (datetime2, convert(varchar(255), [Extent1].[CreationDate], 102) , 102)) > @p__linq__0
如您所见,在执行对话时,此处存在冗余字符串对话。但是,EF会像SQL 'cast(CreationDate as date)'
一样将日期时间转换为SQL中的日期。但事实并非如此。
所以,这里有两种选择。
1-如果你有一个非常庞大的表,性能受冗余字符串对话的影响,你应该在SQL中手动构建你的查询作为存储过程或类似的东西,并从上下文执行它。
2-如果你没有那样的性能考虑;只需使用DbFunctions.TruncateTime(x.date)
var testQueryRecrods = db.weekRecord
.Where(x => x.CityId == CityRecord.Id)
.Where(x => DbFunctions.TruncateTime(x.date) >= fromDate.Date && DbFunctions.TruncateTime(x.date) <= toDate.Date)
.ToList();