Entity framework core 使用实体框架客户端与服务器评估更改
我有以下问题。我正在使用ASP.NET Core 3.1项目和EF Core 我读到服务器和客户端已经改变了,所以我在Core2.1中执行WHERE部分的方式(使用代码中其他地方的变量)似乎不再有效了 因此,如下所示,我已经更改(根据我阅读的内容)在每个部分中使用ToList(),但现在它没有更多地访问数据库(在我的Core 2.1中,根据下面的代码注释,我只会在最后部分使用ToList) 所以现在对于Core 3.1,我需要在初始“//加载数据”部分有一个动态where-我如何在初始部分做一个动态where,或者有没有办法,现在服务器对客户端的更改在EF Core中解决这个问题(注意,在添加ToList之前,是Core 3.1下EF中失败的最终“//搜索”部分)Entity framework core 使用实体框架客户端与服务器评估更改,entity-framework-core,ef-core-3.1,Entity Framework Core,Ef Core 3.1,我有以下问题。我正在使用ASP.NET Core 3.1项目和EF Core 我读到服务器和客户端已经改变了,所以我在Core2.1中执行WHERE部分的方式(使用代码中其他地方的变量)似乎不再有效了 因此,如下所示,我已经更改(根据我阅读的内容)在每个部分中使用ToList(),但现在它没有更多地访问数据库(在我的Core 2.1中,根据下面的代码注释,我只会在最后部分使用ToList) 所以现在对于Core 3.1,我需要在初始“//加载数据”部分有一个动态where-我如何在初始部分做一个
公共列表条目;
//加载数据
var q=await(从_context.KBEntry中的_k开始)
在_k.CategoryId equals _kc.Id上的_context.KBCategory中加入_kc
进入kc2
来自_kc2.DefaultIfEmpty()中的_kc3
选择新的KBEntryListVM()
{
Id=_k.Id,
DateCreated=DateTime.Parse(_k.DateCreated.ToString()),
CategoryId=_k.CategoryId,
CategoryTitle=\u 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();
}
//搜寻
如果(!string.IsNullOrEmpty)
{
q=q.Where(w=>w.Title.ToLower().Contains($“{s.ToLower()}”)| | w.categorytile.ToLower().Contains($“{s.ToLower()}”)| w.Text.ToLower().Contains($“{s.ToLower()).ToList();
}
lstKBEntry=q;//.ToList();这将是Core2.1中唯一一个我想要ToList()的地方
亚瑟
因此,如下所示,我已更改(根据我阅读的内容)在每个部分中使用ToList()
EF Core 3.x+客户端评估异常消息建议(1)
以可以翻译的形式重写查询
或(2)
通过插入对AsEnumerable()、AsAsAsAsyncEnumerable()、ToList()或ToListSync()的调用,显式切换到客户端计算
因此,您选择了更简单的选项(2),但您应该尝试使用更难的选项(1),但从性能角度来看,这是EFC 3.0删除隐式客户评估的主要原因。只有在无法应用选项(1)的情况下,选项(2)才是您的最后手段
异常消息还包含失败的表达式。不幸的是,它不是确切的部分,而是整个表达式(例如整个Where
谓词),因此您需要分析它,找到失败的部分,并尝试用可翻译的结构替换它们
简单数据表达式的一般规则之一是避免显式转换(ToString()
,Parse
)。在数据库中存储日期和数字,而不是字符串,或者在使用旧的现有数据库时使用,并且不允许对其进行更改
在这个特定的查询中,不支持的(不可翻译的)构造很可能是ToString()
调用string
类型属性(例如Title
,Text
).EF Core仍然支持对finalSelect
进行隐式客户端求值,因此如果引用此类表达式之后没有Where
(或其他)子句,您将不会注意到它。但正如开始时所说的,您应该避免使用它们-查询原始数据并让用户使用(UI)执行所需的格式设置
无论如何,我不能确切地说出来,因为您还没有显示您的模型,但是删除ToString()
应该可以使查询可翻译,因此不需要中间ToList()
或类似的客户端物化:
CategoryTitle=\u kc3.Title.Trim(),
Text=_k.Text.Trim(),
Title=_k.Title.Trim()
您可能还应该替换
DateCreated=DateTime.Parse(\k.DateCreated.ToString())
仅仅
DateCreated=\k.DateCreated
因为似乎DateCreated
已经是DateTime
,所以通过字符串的双重转换没有意义,并且会导致类似的问题。即使数据库类型是string,仍然要删除Parse
/ToString
和设置值转换器
因此,如下所示,我已更改(根据我阅读的内容)在每个部分中使用ToList()
EF Core 3.x+客户端评估异常消息建议(1)
以可以翻译的形式重写查询
或(2)
通过插入对AsEnumerable()、AsAsAsAsyncEnumerable()、ToList()或ToListSync()的调用,显式切换到客户端计算
因此,您选择了更简单的选项(2),但您应该尝试使用更难的选项(1),但从性能角度来看,这是EFC 3.0删除隐式客户评估的主要原因。只有在无法应用选项(1)的情况下,选项(2)才是您的最后手段
异常消息还包含失败的表达式。不幸的是,它不是确切的部分,而是整个表达式(例如整个Where
谓词),因此您需要分析它,找到失败的部分,并尝试用可翻译的结构替换它们
简单数据表达式的一般规则之一是避免显式转换(ToString()
,Parse
)。在数据库中存储日期和数字,而不是字符串,或者在使用旧的现有数据时使用
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()