通过函数返回查询结果然后继续查询该结果时的行为是什么?

时间:2011-03-31 10:16:01

标签: linq asp.net-mvc-3 entity-framework-4

我正在使用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 个答案:

答案 0 :(得分:2)

在您的特定情况下,如果对Single()的调用不会导致执行查询,则只有一个查询。不幸的是,我找不到有关它是否有任何信息。由于AsQueryable属性确实是Bananas,因此IQueryable的调用会触发执行。 根据{{​​3}},对Single的调用不会执行您的查询 的结论:
您的代码应该只生成一个查询。

一般来说:
您可以将IQueryable从一种方法传递到另一种方法,而不会被隐式执行 当调用ToList时,以下代码将导致最后执行一个 SQL语句:

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