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

发布于 2024-10-28 17:22:04 字数 2417 浏览 1 评论 0原文

我正在使用 POCO 的 ASP.NET MVC 3 和 Entity Framework 4,并且想要查询一组并选择一些属性以放入我的 viewModel 中。我将画出我的情况的简化版本:

情况:

我有一个包含 Banana 集合的实体 BananaTree

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

预先非常感谢。

I am using ASP.NET MVC 3 with Entity Framework 4 using POCOs and want to query a set and select some properties to put into my viewModel. I will sketch a simplified version of my situation:

Situation:

I have an entity BananaTree containing a collection of 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; }
}

I also have a view model BananaListItemViewModel used in the view showing a list of bananas for a certain banana tree. This view is managed by the BananaTreeController

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

I have a Details action on the controller like so:

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

What I want to change

This works fine and now I only select the items from the database that I need for my view model. However, I want to take out some more logic from my controller and am trying to do this as much as possible.

I would like to have a function in my repository like so:

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

and use it like so:

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

Question

My question is, in this case, will the two queries be combined and go to the database in one go like in my first example or will this first get all the bananas from the tree completely out of the database and perform the second query on that list? I would prefer the first case. If not, could I rewrite the GetBananas query to get that behaviour (for example like the query below)?

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

Thanks very much in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

饮惑 2024-11-04 17:22:04

在您的特定情况下,如果对 Single() 的调用不会导致执行查询,那么它将只是一个查询。不幸的是,我找不到任何关于它是否有效的信息。对 AsQueryable 的调用不会触发执行,因为 Bananas 属性实际上是一个 IQueryable。< br>
根据 http://msdn.microsoft.com/en-us/library/bb156472 .aspx,对 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();
}

In your specific case, it will be only one query, if the call to Single() doesn't lead to the query to be executed. Unfortunately, I couldn't find any info on whether it does or does not. The call to AsQueryable does not trigger the execution as long, as the Bananas property really is an IQueryable.
According to http://msdn.microsoft.com/en-us/library/bb156472.aspx, the call to Single doesn't execute your query.
Conclusion:
You code should result in only one query.

In general:
You can pass an IQueryable from one method to another without it being implicitly executed.
The following code will result in only one SQL statement executed at the end, when the call to ToList happens:

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();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文