使用.Include()

时间:2016-08-22 15:57:33

标签: linq lambda entity-framework-core

这是检索数据的正确方法吗?这是我能够为用户检索具有相应类别的所有任务的唯一方法。如果我在.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);
    }

这个错误:

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)      at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.SimpleNonNullableDependentKeyValueFactory 1.TryCreateFromCurrentValues(InternalEntityEntry entry, TKey& key) at Microsoft.EntityFrameworkCore.Query.Internal.WeakReferenceIdentityMap 1.CreateIncludeKeyComparer(INAVigation navigation,InternalEntityEntry entry)      在Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.IncludeCore(对象实体,导航导航)      在Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.Include(QueryContext queryContext,Object entity,IReadOnlyList 1 navigationPath, IReadOnlyList 1 relatedEntitiesLoaders,Int32 currentNavigationIndex,Boolean queryStateManager)      在Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.Include(QueryContext queryContext,Object entity,IReadOnlyList 1 navigationPath, IReadOnlyList 1 relatedEntitiesLoaders,Boolean queryStateManager)      在Microsoft.EntityFrameworkCore.Query.Internal.GroupJoinInclude.Include(Object entity)      在Microsoft.EntityFrameworkCore.Query.Internal.GroupJoinInclude.Include(Object entity)      在Microsoft.EntityFrameworkCore.Query.QueryMethodProvider。&lt; _GroupJoin&gt; d__26 4.MoveNext() at System.Linq.Enumerable.<SelectManyIterator>d__163 3.MoveNext()      在System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.<_TrackEntities>d__15 2.MoveNext()      在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 .GetAllTask​​sForUser(String username)in:第31行

1 个答案:

答案 0 :(得分:0)

您是否错过了Category实体中ApplicationUser的外键?您只需要为ApplicationUser定义导航属性。尝试设置这种关系; IMO,设置此关系后,错误输出的查询将正常工作。