我有以下查询摘要。我正在使用带有EF Core的ASP.NET Core 3.1项目。
我了解到服务器与客户端已发生变化,因此我过去在Core 2.1中执行WHERE部分的方式(使用代码中其他位置的变量)似乎不再起作用。
因此,如下所示,我已经更改(按照我阅读的内容)在每个部分中都使用ToList(),但是现在它不会更多地访问数据库了(在我的Core 2.1中,我只会在最后一部分中使用ToList按照下面的代码注释。
因此对于Core 3.1,现在我需要在初始的“ //加载数据”部分中有一个动态位置-我该如何在初始部分中动态化,或者有办法,现在服务器与客户端发生变化可以在EF Core中解决(请注意,这是在Core 3.1下EF失败的最后一个“ // Search”部分(在添加ToList之前)
public List<KBEntryListVM> lstKBEntry;
// Load data
var q = await (from _k in _context.KBEntry
join _kc in _context.KBCategory on _k.CategoryId equals _kc.Id
into _kc2
from _kc3 in _kc2.DefaultIfEmpty()
select new KBEntryListVM()
{
Id = _k.Id,
DateCreated = DateTime.Parse(_k.DateCreated.ToString()),
CategoryId = _k.CategoryId,
CategoryTitle = _kc3.Title.ToString().Trim(),
Text = _k.Text.ToString().Trim(),
Title = _k.Title.ToString().Trim()
}).ToListAsync();
// KBCategory
if (!string.IsNullOrEmpty(c) && Guid.TryParse(c.ToString().Trim(), out var newGuid))
{
q = q.Where(w => w.CategoryId == Guid.Parse($"{c.ToString()}")).ToList();
}
// Search
if (!string.IsNullOrEmpty(s))
{
q = q.Where(w => w.Title.ToLower().Contains($"{s.ToLower()}") || w.CategoryTitle.ToLower().Contains($"{s.ToLower()}") || w.Text.ToLower().Contains($"{s.ToLower()}")).ToList();
}
lstKBEntry = q; //.ToList(); this would of been the only place in Core 2.1 I would of had ToList()
亚瑟
答案 0 :(得分:0)
因此,如下所示,我已更改(根据我阅读的内容)在每个部分中使用ToList()
EF Core 3.x +客户端评估异常消息建议任一(1)
以一种可以翻译的形式重写查询
或(2)
通过插入对AsEnumerable(),AsAsyncEnumerable(),ToList()或ToListAsync()的调用来显式切换到客户端评估
因此,您采用的是更容易的选项(2),但是您应该尝试利用较难的选项(1),但从性能的角度来看更好,并且EFC 3.0删除了隐式客户端评估的主要原因。仅在无法应用选项(1)的情况下,选项(2)才是您的最后选择。
异常消息还包含失败的表达式。不幸的是,它不是确切的部分,而是整个表达式(例如整个Where
谓词),因此您需要对其进行分析,找到失败的部分,然后尝试用可翻译的构造替换它们。>
简单数据表达式的一般规则之一是避免显式转换(ToString()
,Parse
)。将日期和数字本身而不是字符串存储在数据库中,或者在使用旧的现有数据库且不允许更改时使用value conversions。
在此特定查询中,最不受支持(不可翻译)的构造很可能是ToString()
类型属性(例如string
,Title
)的Text
调用。 EF Core仍支持 final Select
的隐式客户端评估,因此,如果在引用此类表达式之后没有Where
(或其他)子句,您将不会注意到它。但是正如开头所说,无论如何都应避免使用它们-查询原始数据,并让用法(UI)进行所需的格式化。
无论如何,我无法确切地说出原因,因为您没有显示模型,但是删除ToString()
应该可以使查询可翻译,因此不需要中间ToList()
或类似的客户实现:>
CategoryTitle = _kc3.Title.Trim(),
Text = _k.Text.Trim(),
Title = _k.Title.Trim()
您可能还应该替换
DateCreated = DateTime.Parse(_k.DateCreated.ToString())
只需
DateCreated = _k.DateCreated
因为似乎DateCreated
已经是DateTime
,所以通过字符串进行双重转换没有任何意义,并且会引起类似的麻烦。并且即使数据库类型为字符串,仍请删除Parse
/ ToString
并设置执行该操作的值转换器。