Запрос Entity Framework выполняет два запроса вместо одного - PullRequest
2 голосов
/ 13 марта 2012

Я столкнулся со странным поведением в Entity Framework 4.3.1. В приведенном ниже примере я создаю простую модель и выполняю два разных запроса, которые, по моему мнению, должны быть эквивалентны. Первый использует оператор All, а другой использует комбинацию Where и Any для достижения того же результата.

Первый запрос выглядит так:

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 Ответ

1 голос
/ 13 марта 2012

Я не думаю, что это ошибка.Я просто думаю, что это особенность способа, которым EF генерирует этот конкретный запрос.

Отражены ли отношения между вашим Проектом -> Операцией?А как насчет запроса что-то вроде этого?

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