Каково поведение при возврате результата запроса через функцию и последующем запросе этого результата? - PullRequest
0 голосов
/ 31 марта 2011

Я использую ASP.NET MVC 3 с Entity Framework 4, использующей POCO, и хочу запросить набор и выбрать некоторые свойства для добавления в мою viewModel.Я нарисую упрощенную версию моей ситуации:

Ситуация:

У меня есть объект BananaTree, содержащий коллекцию Banana

public class Banana
{
    public int Id { get; set; }
    public int Size { get; set; }
    public TimeSpan Age { get; set }
    public string Description { get; set; }
}

public class BananaTree
{
    public int Id { get; set; }
    public ICollection<Banana> Bananas { get; set; }
}

У меня также естьмодель представления BananaListItemViewModel, используемая в представлении, показывающем список бананов для определенного бананового дерева.Это представление управляется BananaTreeController

public class BananaListItemViewModel
{
    public int Id { get; set; }
    public TimeSpan Age { get; set }
}

У меня есть действие Подробности на контроллере, например, так:

public ActionResult Details(int bananaTreeId)
{
    var viewModel = from bananaTree in bananaTreeRepository.BananaTrees
                    where bananaTree.Id == bananaTreeId
                    from banana in bananaTree.Bananas
                    select new BananaListItemViewModel
                    {
                        Id = banana.Id,
                        Age = banana.Age
                    };

    return View(viewModel);
}

Что я хочу изменить

Этоработает нормально, и теперь я выбираю только те элементы из базы данных, которые мне нужны для моей модели представления.Тем не менее, я хочу извлечь больше логики из моего контроллера и пытаюсь сделать это как можно больше.

Я хотел бы иметь функцию в моем хранилище, например, так:

IQueryable<Banana> GetBananas(int bananaTreeId)
{
    return (from bananaTree in BananaTrees
            where bananaTree.Id == bananaTreeId
            select bananaTree.Bananas).Single().AsQueryable();
}

и использовать ее так:

public ActionResult Details(int bananaTreeId)
{
    var viewModel = from banana in bananaTreeRepository.GetBananas(bananaTreeId)
                    select new BananaListItemViewModel
                    {
                        Id = banana.Id,
                        Age = banana.Age
                    };

    return View(viewModel);
}

Вопрос

Мой вопрос, в этом случае, будут ли эти два запроса объединены и отправлены в базу данных за один раз, как в моем первом примере, или это сначала позволит полностью вывести все бананы из дерева из базы данных и выполнить второй запрос для этогосписок?Я бы предпочел первый случай.Если нет, могу ли я переписать запрос GetBananas, чтобы получить такое поведение (например, как запрос ниже)?

IQueryable<Banana> GetBananas(int bananaTreeId)
{
    return from bananaTree in BananaTrees
           where bananaTree.Id == bananaTreeId
           from banana in bananaTree.Bananas
           select banana;
}

Заранее большое спасибо.

1 Ответ

2 голосов
/ 31 марта 2011

В вашем конкретном случае это будет только один запрос, если вызов Single() не приведет к выполнению запроса. К сожалению, я не смог найти никакой информации о том, делает это или нет. Вызов AsQueryable не запускает выполнение до тех пор, пока свойство Bananas действительно является IQueryable.
Согласно http://msdn.microsoft.com/en-us/library/bb156472.aspx, вызов Single не выполняет ваш запрос.
Вывод:
Ваш код должен привести только к одному запросу.

В целом:
Вы можете передать IQueryable из одного метода в другой без неявного выполнения.
Следующий код приведет к выполнению только одного оператора SQL в конце, когда произойдет вызов ToList:

IQueryable<Banana> GetBananasByWeight(int weight)
{
    return from banana in Bananas where banana.Weight = weight;
}

IQueryable<Banana> FilterByQuality(IQueryable<Banana> bananaQuery, int quality)
{
    return bananaQuery.Where(b => b.Quality == quality);
}

public List<Banana> GetBananas(int weight, int quality)
{
    var query = GetBananasByWeight(weight);
    var filteredBananas = FilterByQuality(query, quality);
    return filteredBananas.ToList();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...