c# - 在 TPH 上使用 EF 包含

标签 c# entity-framework tph

我已经使用 THP 实现了具有简单继承的代码优先数据库架构: Database diagram

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

var notifications = _context.Notifications;
foreach (var notification in notifications)
{
    Debug.WriteLine((notification is NotificationUser)? ((NotificationUser) notification).TargetUser?.Name : "-");
}

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

是否可以实现用户预加载?我已经尝试编写 _context.Notifications.Include('TargetUser') 以抛出异常。


更新。异常(exception)情况是:

A specified Include path is not valid. The EntityType 'Core.Concrete.NotificationBase' does not declare a navigation property with the name 'TargetUser'.

试图修改this answer到:

var notifications = _context.Notifications.OfType<NotificationUser>()
                .Include(n => n.TargetUser)
                .Cast<NotificationBase>()
                .Union(_context.Notifications.OfType<NotificationPlace>()

但仍然抛出相同的异常。

最佳答案

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

<强>1。网络冗余

选择 ID 然后运行一个查询,用 ID 加载项目是多余的,只需运行这个就可以达到同样的效果

解决方法:

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 个数据库连接,而只会等待一个。您还可以节省一些流量。

<强>2。对被忽略的实体进行分页?

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

解决方案:将 ofType 移到查询的上层

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 时,您应该考虑使用 async/await,因为它不会阻塞线程,从而浪费更少的资源(如果您还没有使用它,这可能需要您重写大量现有代码尽管)。

请研究async/await的优点,并在等待结果等场景中使用它们。

解决方案:改变这个

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

进入这个

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

注意: 然后,您还必须从

更改任何使用此方法的地方
var x = GetNotificationUsers(skip, take);

var x = await GetNotificationUsersAsync(skip, take);

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

关于c# - 在 TPH 上使用 EF 包含,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37070301/

相关文章:

c# - 操作失败 : The relationship could not be changed because one or more of the foreign-key properties is non-nullable

entity-framework - 在 ASP.NET MVC5 Identity 系统中进一步扩展 ApplicationUser 类

c# - 每第 N 个字符/数字拆分一个字符串/数字?

c# - 实现一个非泛型的静态工厂方法以从字符串输入创建各种泛型类(不使用 "dynamic"类型)

.net - Entity Framework 4.1:如何按对象ID删除

c# - 使用 Entity Framework 6 代码优先注释映射 xmltype oracle

c# - 使用条件运算符?避免 if 条件

c# - 调用此字符串 "String"是危险的还是不好的做法?

entity-framework-core - 如何使用 Entity Framework Core 2 中的每层级表 (TPH) 模式将列持久保存为 json

c# - TPH 和多对多关系