.net 实体框架查询执行两个查询,而不是一个查询
我在实体框架4.3.1中遇到了一个奇怪的行为。在下面的示例中,我创建了一个简单的模型并执行了两个不同的查询,我认为这两个查询应该是等价的。第一个使用.net 实体框架查询执行两个查询,而不是一个查询,.net,entity-framework-4,ef-code-first,.net,Entity Framework 4,Ef Code First,我在实体框架4.3.1中遇到了一个奇怪的行为。在下面的示例中,我创建了一个简单的模型并执行了两个不同的查询,我认为这两个查询应该是等价的。第一个使用All操作符,而另一个使用Where和Any的组合来实现相同的结果 第一个查询如下所示: 执行时,它会导致以下两个数据库查询,其中“额外”查询如下所示: SELECT 1 AS [C1], [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name], [Extent1].[Project_Id] AS
All
操作符,而另一个使用Where
和Any
的组合来实现相同的结果
第一个查询如下所示:
执行时,它会导致以下两个数据库查询,其中“额外”查询如下所示:
SELECT
1 AS [C1],
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[Project_Id] AS [Project_Id]
FROM [dbo].[Operations] AS [Extent1]
第二个查询如下所示:
这只执行一个查询,但比较混乱
我不知道为什么第一个版本会引起两个查询。这在我的代码中造成了错误,我无法在一个小示例中重现这些错误
我的问题是:为什么第一个查询执行两个数据库查询?这是我应该报告的错误吗
完整代码如下:
using System.Data.Entity;
using System.Linq;
namespace EFTest {
class Program {
static void Main(string[] args) {
var connStr = @"Data Source=.\SQLServer; Initial catalog = EFTest;"
+ " Integrated Security=True; MultipleActiveResultSets=True";
using (var db = new MyDbContext(connStr)) {
var result = db.Projects // Two queries!
.Where(p => p.Id == 1)
.All(p => db.Operations.Any(
o => o.Name == "foo" && o.Project.Id == p.Id));
}
using (var db = new MyDbContext(connStr)) {
var result = !db.Projects // Single query
.Where(p => p.Id == 1)
.Where(p => !db.Operations.Any(
o => o.Name == "foo" && o.Project.Id == p.Id))
.Any();
}
}
}
public class Project {
public long Id { get; set; }
public string Name { get; set; }
}
public class Operation {
public long Id { get; set; }
public string Name { get; set; }
public virtual Project Project { get; set; }
}
public class MyDbContext : DbContext
{
public virtual IDbSet<Project> Projects { get; set; }
public virtual IDbSet<Operation> Operations { get; set; }
public MyDbContext(string nameOrConnectionString)
: base(nameOrConnectionString) { }
}
}
使用System.Data.Entity;
使用System.Linq;
命名空间EFTest{
班级计划{
静态void Main(字符串[]参数){
var connStr=@“数据源=。\SQLServer;初始目录=EFTest;”
+“集成安全性=True;MultipleActiveResultSets=True”;
使用(var db=newmydbcontext(connStr)){
var result=db.Projects//两个查询!
.其中(p=>p.Id==1)
.All(p=>db.Operations.Any(
o=>o.Name==“foo”&&o.Project.Id==p.Id));
}
使用(var db=newmydbcontext(connStr)){
var result=!db.Projects//单个查询
.其中(p=>p.Id==1)
.Where(p=>!db.Operations.Any(
o=>o.Name==“foo”&&o.Project.Id==p.Id))
.Any();
}
}
}
公共类项目{
公共长Id{get;set;}
公共字符串名称{get;set;}
}
公营课运作{
公共长Id{get;set;}
公共字符串名称{get;set;}
公共虚拟项目{get;set;}
}
公共类MyDbContext:DbContext
{
公共虚拟IDbSet项目{get;set;}
公共虚拟IDbSet操作{get;set;}
公共MyDbContext(字符串名称或连接字符串)
:base(nameOrConnectionString){}
}
}
我认为这不是一个bug。我只是认为这是EF生成特定查询的一种特殊方式
您的项目->运营关系是否已映射?像这样的查询怎么样
var result = !db.Projects
.Any(p => p.Id == 1 && !p.Operations.Any(o => o.Name == "foo");
如果我添加一个操作集合并执行该查询,我将再次得到一个数据库查询。我对理解EF在另一种情况下执行两个查询的原因很感兴趣,因为我一直假设一个linq查询将始终生成一个db查询。
using System.Data.Entity;
using System.Linq;
namespace EFTest {
class Program {
static void Main(string[] args) {
var connStr = @"Data Source=.\SQLServer; Initial catalog = EFTest;"
+ " Integrated Security=True; MultipleActiveResultSets=True";
using (var db = new MyDbContext(connStr)) {
var result = db.Projects // Two queries!
.Where(p => p.Id == 1)
.All(p => db.Operations.Any(
o => o.Name == "foo" && o.Project.Id == p.Id));
}
using (var db = new MyDbContext(connStr)) {
var result = !db.Projects // Single query
.Where(p => p.Id == 1)
.Where(p => !db.Operations.Any(
o => o.Name == "foo" && o.Project.Id == p.Id))
.Any();
}
}
}
public class Project {
public long Id { get; set; }
public string Name { get; set; }
}
public class Operation {
public long Id { get; set; }
public string Name { get; set; }
public virtual Project Project { get; set; }
}
public class MyDbContext : DbContext
{
public virtual IDbSet<Project> Projects { get; set; }
public virtual IDbSet<Operation> Operations { get; set; }
public MyDbContext(string nameOrConnectionString)
: base(nameOrConnectionString) { }
}
}
var result = !db.Projects
.Any(p => p.Id == 1 && !p.Operations.Any(o => o.Name == "foo");