【发布时间】:2018-06-29 19:13:32
【问题描述】:
我是使用实体框架(核心 2.0.1)的新手,据我了解,LINQ 表达式通过实体框架映射到供应商特定的 SQL 查询,例如
from actor in db.Actors
where actor.Name == "Madonna"
|| actor.Name == "Bruce Lee"
select actor
映射到
SELECT *
FROM Actors
WHERE Name = 'Madonna'
OR Name = 'Bruce Lee';
我在某处引用了read
EF/Core 将 Where 查询方法调用转换为 SQL 中的 WHERE 子句,并将谓词表达式树(同样,不是谓词函数)转换为 WHERE 子句中的条件。
假设我想在匹配演员姓名时不区分大小写,并在演员姓名前后允许空格。我需要为此使用正则表达式。我尝试执行以下操作
public static bool Contains1(Actor actor)
{
bool result;
ISet<string> RegexStrSet = new HashSet<string>(
new String[]{
@"Bruce\s+Lee",
@"Madonna"
}
);
result = false; //assumed
for (IEnumerator<String> criteria = RegexStrSet.GetEnumerator(); criteria.MoveNext() && !result;)
{
if (Regex.Match(actor.Name, @"\s*" + criteria.Current + @"\s*", RegexOptions.IgnoreCase).Success)
{
result = true;
}
}
return result;
}
static void Main(string[] args)
{
using (var db = new ActorDbContext())
{
Predicate<Actor> functPred1 = new Predicate<Actor>(Contains1);
if ((from actor in db.Actors
where functPred1(actor)
select actor).Count() == 0
)
{
...
这确实有效。我现在假设 where 谓词没有被映射,而是在返回表的行时运行,因此现在是数据库 SQL 查询
SELECT *
FROM Actors
我的问题是,实体框架有三个关于如何检索行的选项。有吗
-如果表太大,则检索整个表并抛出内存不足运行时异常。
- 尽可能多地检索并再次执行,直到评估整个表。
-一次检索和评估一行
如果它尝试一次检索整个表,我应该怎么做才不会崩溃。
编辑: 我复制并连接了Dixin's Application side logging,以查看以下下划线查询发送到服务器的以下内容。注意:仅包含最相关的日志 sn-ps。
foreach (Actor actor in (from actor in db.Actors
where actor.Name == "Madonna"
|| actor.Name == "Bruce Lee"
select actor)){ }
日志输出sn-ps:
2018-01-20T21:56:17.0846048+00:00 Information 20101 Microsoft.EntityFrameworkCore.Database.Command
Executed DbCommand (57ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [actor].[Id], [actor].[AcademyWinner], [actor].[Age], [actor].[Name]
FROM [Actors] AS [actor]
WHERE [actor].[Name] IN (N'Madonna', N'Bruce Lee')
和
foreach (Actor actor in (from actor in db.Actors
where functPred1(actor)
select actor)){ }
日志输出sn-ps:
2018-01-20T21:56:17.1878434+00:00 Warning 20500 Microsoft.EntityFrameworkCore.Query
The LINQ expression 'where Invoke(__functPred1_0, [actor])' could not be translated and will be evaluated locally.
2018-01-20T21:56:17.2269410+00:00 Information 20101 Microsoft.EntityFrameworkCore.Database.Command
Executed DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [actor].[Id], [actor].[AcademyWinner], [actor].[Age], [actor].[Name]
FROM [Actors] AS [actor]
所以看起来整个表都是从数据库服务器中检索的。实体框架一次只检索表的一个子集,评估行上的谓词函数并继续直到查询测试了表中的每一行以防止内存不足运行时异常,这不是更聪明吗并且不会为其他应用程序占用 RAM。
【问题讨论】:
-
实体框架在正常情况下使用 IQueryable,它不会将整个表加载到内存中 developerhandbook.com/entity-framework/…。但是,在您的特殊情况下,您可以使用 sql profiler 来查看访问服务器的实际查询是什么
-
EF 将一次性检索所有符合条件的行。它没有内部查询结果队列,每个 IQueryable 枚举只会执行一个查询(延迟加载除外)
标签: c# sql entity-framework linq entity-framework-core