【发布时间】:2019-04-02 07:41:24
【问题描述】:
当使用继承的对象时,我正在尝试找到一种方法来过滤我在 EF Core 2.1 中的结果。
我有一个基础模型和几个继承的类(但我只包括了一个):
public class Like {
public int Id { get; set; }
public LikeType LikeType { get; set; }
}
public class DocumentLike : Like {
[ForeignKey(nameof(Document))]
public int DocumentId { get; set; }
public virtual Document Document { get; set; }
}
LikeType 是一个枚举,它被定义为 dbcontext 中的鉴别器。每个Document 都有一个布尔属性.IsCurrent。
要从数据库中获取所有项目,我使用如下查询:
IQueryable<Like> query = _context.Set<Like>()
.Include(x => x.Owner)
.Include(x => (x as DocumentLike).Document.DocumentType)
.Include(x => (x as ProductLike).Product)
.Include(x => (x as TrainingLike).Training)
这很好用,并且返回包含子对象的所有对象,没有任何错误。我要做的是从数据库中获取链接文档具有.IsCurrent == true 的所有项目。我尝试将以下内容添加到上面的查询中,但都导致异常:
.Where(x => (x as DocumentLike).Document.IsCurrent == true)
还有:
.Where(x => x.LikeType == LikeType.Document ? (x as DocumentLike).Document.IsCurrent == true : true)
执行查询时抛出的异常:
NullReferenceException: Object reference not set to an instance of an object.
lambda_method(Closure , TransparentIdentifier<TransparentIdentifier<TransparentIdentifier<TransparentIdentifier<TransparentIdentifier<TransparentIdentifier<TransparentIdentifier<TransparentIdentifier<TransparentIdentifier<TransparentIdentifier<TransparentIdentifier<TransparentIdentifier<Like, ApplicationUser>, Organisation>, Training>, Product>, Platform>, NewsItem>, Event>, Document>, DocumentType>, Course>, CourseType>, ApplicationUser> )
System.Linq.Utilities+<>c__DisplayClass1_0<TSource>.<CombinePredicates>b__0(TSource x)
System.Linq.Enumerable+WhereSelectEnumerableIterator<TSource, TResult>.MoveNext()
Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider._TrackEntities<TOut, TIn>(IEnumerable<TOut> results, QueryContext queryContext, IList<EntityTrackingInfo> entityTrackingInfos, IList<Func<TIn, object>> entityAccessors)+MoveNext()
Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider+ExceptionInterceptor<T>+EnumeratorExceptionInterceptor.MoveNext()
System.Collections.Generic.List<T>.AddEnumerable(IEnumerable<T> enumerable)
System.Linq.Enumerable.ToList<TSource>(IEnumerable<TSource> source)
有没有办法做到这一点?
更新:
澄清一下:我希望得到一个从数据库中返回所有Like-objects 的查询,无论它们的(子)类型如何。如果子类型是DocumentLike,我只想要链接到具有.IsCurrent == true 的文档的对象。
【问题讨论】:
-
如果您只想加载一种类型,请不要添加所有这些包含。使用
_context.Set<Like>().OfType<DocumentLike>()仅加载此类型的实例,但首先阅读client evaluation。如果 EF Core 不支持该运算符,它可以将所有内容加载到内存中,然后尝试过滤数据。确保在配置中添加.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));以防止这种情况发生 -
UPDATE本质上是询问如何过滤特定类型的孩子 -
嗯,它实际上询问了如何根据仅在继承类中可用的属性来过滤对象。
-
条件应该是
x is not DocumentLike or it is and Document.IsCurrent is true。你可以试试.Where(x => !(x is DocumentLike) || ((DocumentLike)x).Document.IsCurrent == true)。如果IsCurrent不可为空,则不需要与true进行比较。不过我还没有尝试过,无论如何我都会使用配置警告来确保 EF 不会尝试在客户端对此进行评估 -
谢谢,这似乎可以解决问题!
标签: c# .net-core entity-framework-core ef-core-2.1