通过函数返回查询结果然后继续查询该结果时的行为是什么?
我正在使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在您的特定情况下,如果对
Single()
的调用不会导致执行查询,那么它将只是一个查询。不幸的是,我找不到任何关于它是否有效的信息。对AsQueryable
的调用不会触发执行,因为Bananas
属性实际上是一个IQueryable
。< br>根据 http://msdn.microsoft.com/en-us/library/bb156472 .aspx,对
Single
的调用不会执行您的查询。结论:
您的代码应该只产生一个查询。
一般来说:
您可以将
IQueryable
从一种方法传递到另一种方法,而无需隐式执行它。当调用
ToList
时,以下代码将导致在最后仅执行一个 SQL 语句: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 toAsQueryable
does not trigger the execution as long, as theBananas
property really is anIQueryable
.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: