【发布时间】:2020-10-16 18:42:55
【问题描述】:
我有一些看起来像这样的实体:
public class MyEvent
{
// ...
public IEnumerable<MyEncounter> Encounters { get; set; } // Navigation property
// ...
}
public class MyEncounter
{
public Guid MyEventID { get; set; }
public MyEvent MyEvent { get; set; } // Navigation property
public Guid? MySpecialProperty { get; set; }
public int Status { get; set; }
//...
}
我想添加一个扩展方法来对 MyEvent 上的 Encounters 集合进行一些过滤,并为其中一个 MyEncounter 实例(特别是 status = 1 的实例)返回 MySpecialProperty 的值。
所以,我写了我的扩展方法:
public static class MyExtensions
{
public static Guid? GetMySpecialProperty(this IEnumerable<MyEncounter> encounters)
{
return encounters.Where(e => e.Status == 1)
.Select(e => e.MySpecialProperty)
.FirstOrDefault();
}
}
现在,我准备好使用我的扩展方法了。我已经大大简化了这一点,以删除不相关的内容:
var qry = MyEventsContext.
.Where(<some logic>)
.Select(x => new MyViewModel
{
SpecialPropValue = x.Encounters.GetMySpecialProperty()
});
这会按预期编译,我已准备好运行查询:
IList<MyViewModel> items = await qry.ToListAsync();
这就是问题所在。只要.ToListAsync() 被执行,我就会得到这个异常:
VerificationException: Method Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor+CustomShaperCompilingExpressionVisitor.PopulateCollection: type argument 'System.Collections.Generic.IEnumerable`1[<fully qualified name of MyEncounter>]' violates the constraint of type parameter 'TCollection'.
内部异常只是稍微详细一点:
ArgumentException: GenericArguments[0], 'System.Collections.Generic.IEnumerable`1[<fully qualified name of MyEncounter>]', on 'Void PopulateCollection[TCollection,TElement,TRelatedEntity](Int32, Microsoft.EntityFrameworkCore.Query.QueryContext, System.Data.Common.DbDataReader, Microsoft.EntityFrameworkCore.Query.Internal.ResultCoordinator, System.Func`3[Microsoft.EntityFrameworkCore.Query.QueryContext,System.Data.Common.DbDataReader,System.Object[]], System.Func`3[Microsoft.EntityFrameworkCore.Query.QueryContext,System.Data.Common.DbDataReader,System.Object[]], System.Func`3[Microsoft.EntityFrameworkCore.Query.QueryContext,System.Data.Common.DbDataReader,System.Object[]], System.Func`5[Microsoft.EntityFrameworkCore.Query.QueryContext,System.Data.Common.DbDataReader,Microsoft.EntityFrameworkCore.Query.Internal.ResultContext,Microsoft.EntityFrameworkCore.Query.Internal.ResultCoordinator,TRelatedEntity])' violates the constraint of type 'TCollection'.
这个异常告诉我什么,有没有办法解决它?据我所知,我已经正确地创建了我的扩展方法。
有趣的是,如果我创建一个扩展方法来获取与条件匹配的 MyEncounters 并在查询中执行 Select/FirstOrDefault,一切都会按预期工作:// Extension method
public static IEnumerable<MyEncounter> GetMySpecialEncounters(this IEnumerable<MyEncounter> encounters)
{
return encounters.Where(e => e.Status == 1)
}
// Query
var qry = MyEventsContext.
.Where(<some logic>)
.Select(x => new MyViewModel
{
SpecialPropValue = x.Encounters.GetMySpecialEncounters()
.Select(x => x.MySpecialProperty)
.FirstOrDefault()
});
罢工>
我对上述内容有误。在查询中使用该扩展方法会导致此异常:
When called from 'VisitLambda', rewriting a node of type 'System.Linq.Expressions.ParameterExpression' must return a non-null value of the same type
起作用的是在查询中执行所有逻辑,根本没有扩展方法:
// Query
var qry = MyEventsContext.
.Where(<some logic>)
.Select(x => new MyViewModel
{
SpecialPropValue = x.Encounters.Where(e => e.Status == 1)
.Select(x => x.MySpecialProperty)
.FirstOrDefault()
});
【问题讨论】:
-
您的代码无法编译。
-
@TanveerBadar 它并不是真的要编译。我已经从一堆不同的文件中包含了相关内容的 sn-ps。
-
我应该更清楚。
MyEvent的导航道具缺少名称,因此有点难以理解。不管能不能编译,“心理”都很难编译。 -
另外,看看使用
ToList()是否可以解决问题。我自己也注意到异步方法有一些奇怪的行为。 -
@TanveerBadar 啊,我明白了!我已经修正了那个错字。我也尝试在执行查询时使用
.ToList(),但它没有改变任何东西。
标签: c# entity-framework-core asp.net-core-mvc