3

THP を使用して、単純な継承を使用してコード ファーストの db アーキテクチャを実装しました。 データベース図

そして、すべてのタイプのすべての通知を照会する必要があります。 テーブルのTargetUserプロパティは関連付けです。NotificationUser次のコードを実行しようとしています:

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

データベースのプロパティTargetUserは外部キーを修正するように設定されていますが、コードでは結果が得られません。遅延読み込みが有効になっています。

ユーザーの熱心な読み込みは可能ですか? 私はすでに_context.Notifications.Include('TargetUser')バイトを書き込もうとしましたが、例外がスローされました。


更新。例外は次のとおりです。

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

この回答を次のように変更しようとしました:

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

それでも同じ例外がスローされます。

4

3 に答える 3

2

これが古いスレッドであることはわかっていますが、同じ解決策を探している人のためにいくつかの改善点を投稿したいと思います.

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 つの DB 接続を待機するのではなく、1 つだけ待機します。また、トラフィックを節約できます。

2. 無視されたエンティティのページング?

この特定のメソッドは、継承されたタイプのエンティティを表示するためだけに使用されると想定されるため、Skip と Take は、そのタイプのエンティティのみで直接動作すると予想されます。たとえば、10 人のユーザーではなく、10 人の NotificationUsers をスキップしたい (たとえば、そのうちの 4 つだけが NotificationUsers です)。

解決策: 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);

そして、そのメソッドを非同期にして、同様にタスクを返します

于 2017-11-06T13:55:28.533 に答える