【发布时间】:2016-12-29 06:21:27
【问题描述】:
这是检索数据的正确方法吗?这是我能够为用户检索具有相应类别的所有任务的唯一方法。如果我在 .ToList() 之前有 where 子句,它会给我一个例外(ApplicationUser 将为空)。我不喜欢这种方法的地方是我先从数据库中检索所有数据,然后再将其解析得更远,只为特定用户返回数据。在某些情况下, .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);
}
这个出错了:
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)
{
}
从 Profiler 检索到的生成的工作 sql 语句。当我运行生成的查询时,它会检索数据,但它会使用 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]
这一项有效,但结果不包括 Category 和 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; }
}
错误堆栈跟踪:
在 lambda_method(Closure , InternalEntityEntry ) 在 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.SimpleNonNullableDependentKeyValueFactory
1.TryCreateFromCurrentValues(InternalEntityEntry entry, TKey& key) at Microsoft.EntityFrameworkCore.Query.Internal.WeakReferenceIdentityMap1.CreateIncludeKeyComparer(INavigation 导航,InternalEntityEntry 条目) 在 Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.IncludeCore(对象实体,INavigation 导航) 在 Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.Include(QueryContext queryContext,对象实体,IReadOnlyList1 navigationPath, IReadOnlyList1 relatedEntitiesLoaders,Int32 currentNavigationIndex,布尔查询状态管理器) 在 Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.Include(QueryContext queryContext,对象实体,IReadOnlyList1 navigationPath, IReadOnlyList1 relatedEntitiesLoaders,布尔查询状态管理器) 在 Microsoft.EntityFrameworkCore.Query.Internal.GroupJoinInclude.Include(对象实体) 在 Microsoft.EntityFrameworkCore.Query.Internal.GroupJoinInclude.Include(对象实体) 在 Microsoft.EntityFrameworkCore.Query.QueryMethodProvider.<_groupjoin>d__264.MoveNext() at System.Linq.Enumerable.<SelectManyIterator>d__1633.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.<_TrackEntities>d__152.MoveNext() 在 Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor1.EnumeratorExceptionInterceptor.MoveNext() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 源) 在 .GetAllTasksForUser(String username) in :line 31
【问题讨论】:
-
如果我在 .ToList() 之前有 where 子句,它会给我一个例外(ApplicationUser 将为空) 不,它不会“给你一个例外”。在实现查询之前,您编写的所有内容都只是用于生成 SQL 查询的元数据。这个
Where应该在ToList之前。Include与查询无关,但控制将在您的对象中填充的内容,同样仅在查询具体化时。 -
Category和ApplicationUser是Lists还是单个对象? -
它给了我例外,就像我提到的那样,它说“对象引用未设置为对象的实例。” (它适用于 ApplicationUser)。我认为你是不正确的,那是 .Include() 造成的。
-
假设你得到一个异常,你能发布异常堆栈跟踪吗?
-
当然,刚刚更新了我的问题
标签: linq lambda entity-framework-core