首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在TPH上使用EF Include

在TPH上使用EF Include
EN

Stack Overflow用户
提问于 2016-05-06 10:40:11
回答 4查看 1.3K关注 0票数 4

我使用THP实现了具有简单继承的代码first db体系结构:

我需要查询所有类型的通知。TargetUser属性在NotificationUser表中是一个关联。我正在尝试执行下一个代码:

代码语言:javascript
复制
var notifications = _context.Notifications;
foreach (var notification in notifications)
{
    Debug.WriteLine((notification is NotificationUser)? ((NotificationUser) notification).TargetUser?.Name : "-");
}

在数据库propety中,TargetUser被设置为更正外键,但在代码中我没有得到任何结果。启用延迟加载。

用户是否有可能急于加载?我已经尝试过写_context.Notifications.Include('TargetUser')字节,它会抛出一个异常。

Upd。例外是:

代码语言:javascript
复制
A specified Include path is not valid. The EntityType 'Core.Concrete.NotificationBase' does not declare a navigation property with the name 'TargetUser'.

试图将this answer修改为:

代码语言:javascript
复制
var notifications = _context.Notifications.OfType<NotificationUser>()
                .Include(n => n.TargetUser)
                .Cast<NotificationBase>()
                .Union(_context.Notifications.OfType<NotificationPlace>()

但是仍然会抛出相同的异常。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-05-06 13:51:35

已经尝试了许多不同的解决方案,但没有一个适合我的需求,因为我正在开发一个API,而且查询必须支持分页,并向数据库发出不断的请求(并且没有在内存中加载所有实体)。

终于找到了一个解决办法,也许不是最好的,但现在已经足够了。首先,我请求部分有序数据(分页逻辑):

代码语言:javascript
复制
var notifications = _context.Notifications
            .OrderByDescending(n => n.DateTime)
            .Skip(offset)
            .Take(limit);

(此时我对任何属性都不感兴趣)接下来,我将获取每个实体类型的加载项的Id:

代码语言:javascript
复制
var ids = notifications.OfType<NotificationUser>().Select(n => n.Id).ToList();

最后,加载特定实体,包括所有属性:

代码语言:javascript
复制
var userNotifications = _context.Notifications.OfType<NotificationUser>()
             .Include(n => n.TargetUser)
             .Include(n => n.TargetUser.Images)
             .Where(n => ids.Contains(n.Id))
             .ToList();

所有实体再一次进入列表并排序。

这里有很多不好的东西,希望有人能提供更好的解决方案。

票数 0
EN

Stack Overflow用户

发布于 2017-11-06 13:55:28

我知道这是一个旧的线程,但我仍然想为寻求相同解决方案的人发布一些改进。

1.网络冗余

选择is,然后运行一个查询,用is加载项目是多余的,只要运行以下命令就可以达到同样的效果。

解决方案:

代码语言:javascript
复制
var userNotifications = _context.Notifications
    .OrderByDescending(n => n.DateTime)
    .Skip(offset)
    .Take(limit)
    .OfType<NotificationUser>()
    .Include(n => n.TargetUser)
    .Include(n => n.TargetUser.Images)
    .ToList();

这样,您就不会等待2个DB连接,而只是一个。你也节省了一些交通。

2.对被忽略的实体进行分页?

人们可能会假设,这个特定的方法只用于查看继承类型的实体,因此我希望Skip并采取直接工作在所述类型的实体上。例如,我想跳过10个NotificationUsers,而不是10个用户(其中只有4个是NotificationUsers )。

解决方案:将ofType移到查询的更高位置

代码语言:javascript
复制
var userNotifications = _context.Notifications
    .OfType<NotificationUser>()
    .OrderByDescending(n => n.DateTime)
    .Skip(offset)
    .Take(limit)
    .Include(n => n.TargetUser)
    .Include(n => n.TargetUser.Images)
    .ToList();

3.异步/等待

在编写API时,您应该考虑使用异步/等待,因为这样不会阻塞线程,因此浪费更少的资源(这可能需要您重写大量现有代码,如果您不使用它的话)。

请研究异步/等待的优点,并在诸如等待结果的场景中使用它们。

解决方案:更改此

代码语言:javascript
复制
private List<NotificationUser> GetNotificationUsers(int offset, int limit)
    {
        return _context.Notifications
                .OfType<NotificationUser>()
                .OrderByDescending(n => n.DateTime)
                .Skip(offset)
                .Take(limit)
                .Include(n => n.TargetUser)
                .Include(n => n.TargetUser.Images)
                .ToList();
    }

进入到这个

代码语言:javascript
复制
private async Task<List<NotificationUser>> GetNotificationUsersAsync(int offset, int limit)
    {
        return await _context.Notifications
                .OfType<NotificationUser>()
                .OrderByDescending(n => n.DateTime)
                .Skip(offset)
                .Take(limit)
                .Include(n => n.TargetUser)
                .Include(n => n.TargetUser.Images)
                .ToListAsync();
    }

注意:然后,您还必须更改使用此方法的任何位置。

代码语言:javascript
复制
var x = GetNotificationUsers(skip, take);

代码语言:javascript
复制
var x = await GetNotificationUsersAsync(skip, take);

并使该方法异步并返回一个任务。

票数 2
EN

Stack Overflow用户

发布于 2016-05-06 12:26:09

我不知道你会和多少实体一起工作。如果可能的话,我将尝试在DB服务器上进行联合,而不是在DB服务器上:

代码语言:javascript
复制
var userNotifications = _context.Notifications.OfType<NotificationUser>()
                                .Include(n => n.TargetUser).ToList();
var placeNotifications = _context.Notifications.OfType<NotificationPlace>().ToList();
var notifications = userNotifications.Union(placeNotifications);

请参阅https://stackoverflow.com/a/27643393/2342504

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37070301

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档