Oli*_*hia 43 entity-framework count
我一直想知道这个问题,所以我认为使用我的第一个Stack Overflow帖子来询问它是值得的.
想象一下,我与相关的消息列表进行了讨论:
DiscussionCategory discussionCategory = _repository.GetDiscussionCategory(id);
Run Code Online (Sandbox Code Playgroud)
discussionCategory.Discussions是当前未加载的Discussion实体列表.
我想要的是能够遍历discussionCategory中的讨论并说明每次讨论中有多少消息而不提取消息数据.
当我尝试这个之前,我必须加载讨论和消息,以便我可以做这样的事情:
discussionCategory.Discussions.Attach(Model.Discussions.CreateSourceQuery().Include("Messages").AsEnumerable());
foreach(Discussion discussion in discussionCategory.Discussions)
{
int messageCount = discussion.Messages.Count;
Console.WriteLine(messageCount);
}
Run Code Online (Sandbox Code Playgroud)
这对我来说似乎相当低效,因为我从数据库中取出可能有数百个消息体并将它们保存在内存中,而我想做的就是将它们的数量用于表示目的.
我已经看到了一些涉及这个问题的问题,但他们似乎没有直接解决它.
提前感谢您对此主题的任何想法.
更新 - 根据要求提供更多代码:
public ActionResult Details(int id)
{
Project project = _repository.GetProject(id);
return View(project);
}
Run Code Online (Sandbox Code Playgroud)
然后在视图中(只是为了测试它):
Model.Discussions.Load();
var items = from d in Model.Discussions select new { Id = d.Id, Name = d.Name, MessageCount = d.Messages.Count() };
foreach (var item in items) {
//etc
Run Code Online (Sandbox Code Playgroud)
我希望这会让我的问题更加清晰.如果您需要更多代码详细信息,请与我们联系.
Cra*_*ntz 39
简单; 只需投射到POCO(或匿名)类型:
var q = from d in Model.Discussions
select new DiscussionPresentation
{
Subject = d.Subject,
MessageCount = d.Messages.Count(),
};
Run Code Online (Sandbox Code Playgroud)
当您查看生成的SQL时,您将看到Count()由DB服务器完成.
请注意,这适用于EF 1和EF 4.
Ric*_*rdo 10
如果您使用的是Entity Framework 4.1或更高版本,则可以使用:
var discussion = _repository.GetDiscussionCategory(id);
// Count how many messages the discussion has
var messageCount = context.Entry(discussion)
.Collection(d => d.Messages)
.Query()
.Count();
Run Code Online (Sandbox Code Playgroud)
来源:http://msdn.microsoft.com/en-US/data/jj574232
我知道这是一个老问题,但它似乎是一个持续存在的问题,上面的答案都没有提供一个很好的方法来处理列表视图中的SQL聚合.
我在模板和示例中假设直接POCO模型和Code First.虽然从DBA的角度来看,SQL View解决方案很不错,但它重新引入了并行维护代码和数据库结构的挑战.对于简单的SQL聚合查询,您不会从View中看到太多的速度增益.您真正需要避免的是多个(n + 1)数据库查询,如上例所示.如果您有5000个父实体并且您正在计算子实体(例如,每次讨论的消息),那就是5001个SQL查询.
您可以在单个SQL查询中返回所有这些计数.这是如何做.
使用命名空间中的[NotMapped]数据注释向您的类模型添加占位符属性System.ComponentModel.DataAnnotations.Schema.这使您可以存储计算数据,而无需实际向数据库添加列或投影到不必要的View模型.
...
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MyProject.Models
{
public class Discussion
{
[Key]
public int ID { get; set; }
...
[NotMapped]
public int MessageCount { get; set; }
public virtual ICollection<Message> Messages { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)在Controller中,获取父对象列表.
var discussions = db.Discussions.ToList();
Run Code Online (Sandbox Code Playgroud)捕获字典中的计数.这会生成一个包含所有父ID和子对象计数的SQL GROUP BY查询.(假设DiscussionID是FK Messages.)
var _counts = db.Messages.GroupBy(m => m.DiscussionID).ToDictionary(d => d.Key, d => d.Count());
Run Code Online (Sandbox Code Playgroud)遍历父对象,从字典中查找计数,并存储在占位符属性中.
foreach (var d in discussions)
{
d.MessageCount = (_counts.ContainsKey(d.ID)) ? _counts[d.ID] : 0;
}
Run Code Online (Sandbox Code Playgroud)返回您的讨论列表.
return View(discussions);
Run Code Online (Sandbox Code Playgroud)MessageCount在视图中引用该属性.
@foreach (var item in Model) {
...
@item.MessageCount
...
}
Run Code Online (Sandbox Code Playgroud)是的,您可以将该字典填充到ViewBag中并直接在View中进行查找,但这会使用不需要的代码来混淆您的视图.
最后,我希望EF有办法做"懒惰计数".延迟加载和显式加载的问题是你正在加载对象.如果你需要加载计数,这是一个潜在的性能问题.延迟计数不能解决列表视图中的n + 1问题,但是能够@item.Messages.Count从View 调用而不必担心可能加载大量不需要的对象数据肯定会很好.
希望这可以帮助.
| 归档时间: |
|
| 查看次数: |
20108 次 |
| 最近记录: |