2016-08-22 15 views
0

これはデータを取得する正しいアプローチですか?これは、ユーザーの対応するカテゴリを持つすべてのタスクを取得できる唯一の方法です。 .ToList()の前にwhere句を指定すると、例外が発生します(ApplicationUserはnullになります)。私がこのアプローチについて気にしていないことは、データベースからすべてのデータを最初に取り出し、特定のユーザーのためだけにデータを返すようにさらに解析することです。いくつかのケースでは、インクルード()メソッドは私が想定しているように動作しません。.Include()を使用して複数のテーブルからデータを取得する

public IEnumerable<Task> GetAllTasksForUser(string username) 
    { 
     return _db.Tasks 
       .Include(t => t.Category) 
       .Include(t => t.Category.ApplicationUser) 
       .ToList() 
       .Where(t => t.Category.ApplicationUser.UserName == username); 
    } 

この1つはアウトerroringさ:プロファイラから取得したSQL文を作業

try 
     { 
      var x = _db.Tasks 
       .Include(t => t.Category) 
       .Include(t => t.Category.ApplicationUser) 
       .Where(t => t.Category.ApplicationUser.UserName == username) 
       .ToList(); 

     } 
     catch(Exception ex) 
     { 

     } 

を生成しました。生成されたクエリを実行すると、データが取得されますが、linqを使用して前述の例外がスローされます。この.INCLUDEは()私を殺している:

> SELECT [t].[TaskId], [t].[CategoryId], [t].[Description], [t].[Name], [t].[Timestamp], [t.Category].[CategoryId], [t.Category].[Description], [t.Category].[Name], [t.Category].[Timestamp], [t.Category].[UserId], [t.Category.ApplicationUser].[Id], [t.Category.ApplicationUser].[AccessFailedCount], [t.Category.ApplicationUser].[ConcurrencyStamp], [t.Category.ApplicationUser].[Email], [t.Category.ApplicationUser].[EmailConfirmed], [t.Category.ApplicationUser].[LockoutEnabled], [t.Category.ApplicationUser].[LockoutEnd], [t.Category.ApplicationUser].[NormalizedEmail], [t.Category.ApplicationUser].[NormalizedUserName], [t.Category.ApplicationUser].[PasswordHash], [t.Category.ApplicationUser].[PhoneNumber], [t.Category.ApplicationUser].[PhoneNumberConfirmed], [t.Category.ApplicationUser].[SecurityStamp], [t.Category.ApplicationUser].[TwoFactorEnabled], [t.Category.ApplicationUser].[UserName], [c].[CategoryId], [c].[Description], [c].[Name], [c].[Timestamp], [c].[UserId], [a].[Id], [a].[AccessFailedCount], [a].[ConcurrencyStamp], [a].[Email], [a].[EmailConfirmed], [a].[LockoutEnabled], [a].[LockoutEnd], [a].[NormalizedEmail], [a].[NormalizedUserName], [a].[PasswordHash], [a].[PhoneNumber], [a].[PhoneNumberConfirmed], [a].[SecurityStamp], [a].[TwoFactorEnabled], [a].[UserName], [c0].[CategoryId], [c0].[Description], [c0].[Name], [c0].[Timestamp], [c0].[UserId] 
FROM [Tasks] AS [t] 
INNER JOIN [Categories] AS [t.Category] ON [t].[CategoryId] = [t.Category].[CategoryId] 
LEFT JOIN [AspNetUsers] AS [t.Category.ApplicationUser] ON [t.Category].[UserId] = [t.Category.ApplicationUser].[Id] 
INNER JOIN [Categories] AS [c] ON [t].[CategoryId] = [c].[CategoryId] 
LEFT JOIN [AspNetUsers] AS [a] ON [c].[UserId] = [a].[Id] 
INNER JOIN [Categories] AS [c0] ON [t].[CategoryId] = [c0].[CategoryId] 
ORDER BY [t.Category].[UserId] 

をこの1つは動作しますが、結果はカテゴリーとApplicationUserが含まれていません。

return _db.Tasks 
.Where(t => t.Category.ApplicationUser.UserName == username) 
.ToList(); 

そして、私のモデル:

public class Task 
{ 
    [Key] 
    public int TaskId { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public DateTime Timestamp { get; set; } 
    public int CategoryId { get; set; } 

    public virtual Category Category { get; set; } 
} 

    public class Category 
{ 
    [Key] 
    public int CategoryId { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public DateTime Timestamp { get; set; } 

    public string UserId { get; set; } 
    [ForeignKey("UserId")] 
    public virtual ApplicationUser ApplicationUser { get; set; } 

    public virtual ICollection<Task> Tasks { get; set; } 
} 

public class ApplicationUser : IdentityUser 
{ 
    public virtual ICollection<Category> Categories { get; set; } 
} 

エラースタックトレース:

at lambda_method(Closure , InternalEntityEntry) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.SimpleNonNullableDependentKeyValueFactory 1.TryCreateFromCurrentValues(InternalEntityEntry entry, TKey& key) at Microsoft.EntityFrameworkCore.Query.Internal.WeakReferenceIdentityMap 1.CreateIncludeKeyComparer(INavigation navigation, InternalEntityEntry entry) at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.IncludeCore(Object entity, INavigation navigation) at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.Include(QueryContext queryContext, Object entity, IReadOnlyList 1 navigationPath, IReadOnlyList 1 relatedEntitiesLoaders, Int32 currentNavigationIndex, Boolean queryStateManager) at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.Include(QueryContext queryContext, Object entity, IReadOnlyList 1 navigationPath, IReadOnlyList 1 relatedEntitiesLoaders, Boolean queryStateManager) at Microsoft.EntityFrameworkCore.Query.Internal.GroupJoinInclude.Include(Object entity) at Microsoft.EntityFrameworkCore.Query.Internal.GroupJoinInclude.Include(Object entity) at Microsoft.EntityFrameworkCore.Query.QueryMethodProvider.<_GroupJoin>d__26 4.MoveNext() at System.Linq.Enumerable.<SelectManyIterator>d__163 3.MoveNext() at System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.<_TrackEntities>d__15 2.MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor 1.EnumeratorExceptionInterceptor.MoveNext() at System.Collections.Generic.List 1..ctor(IEnumerable 1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable 1 source) at .GetAllTasksForUser(String username) in :line 31

+1

* .ToList()の前にwhere句を使用すると、例外が発生します(ApplicationUserはnullになります)。*いいえ、「例外が発生しません」。クエリを具体化する前に、あなたが書くのはSQLクエリを生成するためのメタデータだけです。この 'Where'は' ToList'の前でなければなりません。 'Include'は問合せには関係がありませんが、オブジェクトに移入される内容を制御します。 –

+0

'Category'と' ApplicationUser'は 'Lists'または単一のオブジェクトですか? – Sampath

+0

それは私に言及したように私に例外を与え、それは "オブジェクトリファレンスはオブジェクトのインスタンスに設定されていません"と言います。 (これはApplicationUser用です)。私はあなたが間違っていると思います。インクルード()がそれを引き起こしています。 – lucas

答えて

0

CategoryエンティティのApplicationUserへの外部キーを見逃しましたか? ApplicationUserに定義されたナビゲーションプロパティのみがあります。この関係を設定してみてください。 IMO、この関係が設定されると、エラーが正常に機能するクエリ。

+0

良い点ですが、私の問題は解決しませんでした。モデルを更新してテーブルを再生成しましたが、今ではカテゴリにユーザーの外部キーがありますが、同じ問題です。 – lucas

+0

@lucasでも、あなたのエンティティにその外部キーが表示されません。 – Developer

+0

質問を更新します...完了しました。データベースのデータが適切に入力されました。テーブルのカテゴリに対応するuserIdがあります – lucas

関連する問題