【发布时间】:2016-07-20 03:18:46
【问题描述】:
我有以下抽象类:
public abstract class Notification
{
public Notification()
{
this.receivedDate = DateTime.Now.ToUniversalTime();
}
public int Id { get; set; }
public DateTime receivedDate { get; set; }
public bool unread { get; set; }
public virtual ApplicationUser recipient { get; set; }
}
有几个类继承自它,例如ProfileViewNotification 和NewMessageNotification:
public class ProfileViewNotification: Notification
{
public virtual ApplicationUser Viewer { get; set; }
}
public class NewMessageNotification: Notification
{
public virtual Message Message { get; set; }
}
我有以下方法来查询我的数据库中的所有Notification,并将给定的ApplicationUser 作为recipient:
public static List<NotificationApiViewModel> GetNotificationsForUser(string idOfUser)
{
List<NotificationApiViewModel> resultAsApiViewModel = new List<NotificationApiViewModel>();
List<ProfileViewNotification> ofProfileViewNotificationType = null;
List<NewMessageNotification> ofNewMessageNotificationType = null;
try
{
using (var context = new ApplicationDbContext())
{
var query = context.Notifications.Where(c => c.recipient.Id == idOfUser);
ofNewMessageNotificationType = query.OfType<NewMessageNotification>().Any() ?
query.OfType<NewMessageNotification>()
.Include(n => n.recipient)
.Include(n => n.recipient.MyProfile)
.Include(n => n.recipient.MyProfile.ProfileImages)
.Include(n => n.Message)
.Include(n => n.Message.Author)
.Include(n => n.Message.Author.MyProfile)
.Include(n => n.Message.Author.MyProfile.ProfileImages)
.Include(n => n.Message.Recipient)
.Include(n => n.Message.Recipient.MyProfile)
.Include(n => n.Message.Recipient.MyProfile.ProfileImages)
.ToList()
: null;
ofProfileViewNotificationType = query.OfType<ProfileViewNotification>().Any() ?
query.OfType<ProfileViewNotification>()
.Include(n => n.recipient)
.Include(n => n.recipient.MyProfile)
.Include(n => n.recipient.MyProfile.ProfileImages)
.Include(n => n.Viewer)
.Include(n => n.Viewer.MyProfile)
.Include(n => n.Viewer.MyProfile.ProfileImages)
.ToList()
: null;
}
}
catch (Exception ex)
{
//Log issue
}
if (ofNewMessageNotificationType != null)
{
foreach (var n in ofNewMessageNotificationType)
{
resultAsApiViewModel.Add(NotificationApiViewModel.ConvertToApiViewModel(n));
}
}
if (ofProfileViewNotificationType != null)
{
foreach (var n in ofProfileViewNotificationType)
{
resultAsApiViewModel.Add(NotificationApiViewModel.ConvertToApiViewModel(n));
}
}
return resultAsApiViewModel;
}
需要注意的是,我的ConvertToApiViewModel 方法都没有查询数据库,这就是为什么我在原始查询中包含所有这些Include。此外,为简洁起见,以上仅包括两种类型的通知,但我总共有十几种。
我的问题是我的方法非常慢。对于只有 20 条通知的用户,需要一分钟多的时间才能完成!
谁能告诉我我做错了什么?
【问题讨论】:
-
我想你应该看看生成的 sql 查询并分析它们,看看你是否缺少一些索引。
-
@KiNeTiC 感谢您的评论。你能指导我如何做到这一点吗?我不知道如何查看生成的 sql 查询,我不确定您所说的“缺少一些索引”是什么意思
-
对于像这样的复杂查询(很多包含),我建议您改用 LINQ,因为您可以轻松选择所需的字段...您在这里所做的实际上是从数据库中获取所有内容,即远非最佳。
-
问题是嵌套include的数量,它在sql查询中生成了太多
joins。我认为没有 EF 解决方法,所以你应该使用 sql 查询。看看stackoverflow.com/questions/2086894/optimizing-multiple-joins -
如何从 EF6 获取生成的查询:stackoverflow.com/questions/1412863/…
标签: c# asp.net-mvc entity-framework