これはデータを取得する正しいアプローチですか?これは、ユーザーの対応するカテゴリを持つすべてのタスクを取得できる唯一の方法です。 .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, IReadOnlyList1 navigationPath, IReadOnlyList
1 relatedEntitiesLoaders, Int32 currentNavigationIndex, Boolean queryStateManager) at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.Include(QueryContext queryContext, Object entity, IReadOnlyList1 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__264.MoveNext() at System.Linq.Enumerable.<SelectManyIterator>d__163
3.MoveNext() at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.<_TrackEntities>d__15
2.MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor1.EnumeratorExceptionInterceptor.MoveNext() at System.Collections.Generic.List
1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable
1 source) at .GetAllTasksForUser(String username) in :line 31
* .ToList()の前にwhere句を使用すると、例外が発生します(ApplicationUserはnullになります)。*いいえ、「例外が発生しません」。クエリを具体化する前に、あなたが書くのはSQLクエリを生成するためのメタデータだけです。この 'Where'は' ToList'の前でなければなりません。 'Include'は問合せには関係がありませんが、オブジェクトに移入される内容を制御します。 –
'Category'と' ApplicationUser'は 'Lists'または単一のオブジェクトですか? – Sampath
それは私に言及したように私に例外を与え、それは "オブジェクトリファレンスはオブジェクトのインスタンスに設定されていません"と言います。 (これはApplicationUser用です)。私はあなたが間違っていると思います。インクルード()がそれを引き起こしています。 – lucas