实体框架查询执行两个查询而不是一个查询

时间:2012-03-13 19:25:47

标签: .net entity-framework-4 ef-code-first

我在Entity Framework 4.3.1中遇到了一个奇怪的行为。在下面的示例中,我正在创建一个简单的模型并执行两个不同的查询,我认为这些查询应该是等效的。第一个使用All运算符,而另一个使用WhereAny的组合来获得相同的结果。

第一个查询如下所示:

var result = db.Projects
    .Where(p => p.Id == 1)
    .All(p => db.Operations.Any(o => o.Name == "foo" && o.Project.Id == p.Id));

执行时会导致以下两个数据库查询,其中“额外”数据库查询如下所示:

SELECT 
1 AS [C1], 
[Extent1].[Id] AS [Id], 
[Extent1].[Name] AS [Name], 
[Extent1].[Project_Id] AS [Project_Id]
FROM [dbo].[Operations] AS [Extent1]

第二个查询如下所示:

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();

这会执行单个查询,但更加混乱。

我不知道为什么第一个版本导致两个查询。这导致了我的代码中的错误,我在一个小例子中无法重现。

我的问题是:为什么第一个查询执行两次数据库查询?这是我应该报告的错误吗?


以下完整代码:

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) { }
    }
}

1 个答案:

答案 0 :(得分:1)

我不认为这是一个错误。我只是认为这是EF生成特定查询的方式的特质。

您的项目 - &gt;操作关系映射?这样的查询怎么样?

var result = !db.Projects
    .Any(p => p.Id == 1 && !p.Operations.Any(o => o.Name == "foo");