Linq - EntityFramework NotSupportedException

时间:2016-01-26 13:11:11

标签: c# entity-framework linq entity-framework-6

我有一个如下所示的查询:

var caseList = (from x in context.Cases
         where allowedCaseIds.Contains(x => x.CaseId)
         select new Case {
            CaseId = x.CaseId,
            NotifierId = x.NotifierId,
            Notifier = x.NotifierId.HasValue ? new Notifier { Name = x.Notifier.Name } : null // This line throws exception
         }).ToList();

Case班级可以有0..1 Notifier

上述查询将产生以下System.NotSupportedException

  

无法创建类型为' Models.Notifier'的空常量值。仅支持实体类型,枚举类型或基元类型   在这种情况下。

目前,我找到的唯一解决方法是循环查询结果并手动填充Notifier,如下所示:

foreach (var c in caseList.Where(x => x.NotifierId.HasValue)
{
    c.Notifier = (from x in context.Notifiers 
                 where x.CaseId == c.CaseId
                 select new Notifier {
                     Name = x.Name
                 }).FirstOrDefault();
}

但我真的不想这样做,因为在我的实际情况中,它会产生数百个额外的查询。

对于像这样的情况,有没有可能的解决方案?

2 个答案:

答案 0 :(得分:4)

我认为你需要分两步完成。首先,您可以在单个查询中仅使用匿名类型获取所需的数据:

var caseList = (from x in context.Cases
     where allowedCaseIds.Contains(x => x.CaseId)
     select new {
        CaseId = x.CaseId,
        NotifierId = x.NotifierId,
        NotifierName = x.Notifier.Name
     }).ToList();

之后,你可以在记忆中工作:

List<Case> cases = new List<Case>();
foreach (var c in caseList)
{
    var case = new Case();
    case.CaseId = c.CaseId;
    case.NotifierId = c.NotifierId;
    case.NotifierName = c.NotifierId.HasValue ? c.NotifierName : null;
    cases.Add(case);
}

答案 1 :(得分:0)

您可以尝试将查询编写为函数调用链而不是查询表达式,然后在其间放置.AsEnumerable()

var caseList = context.Clases
    .Where(x => allowedCaseIds.Contains(x.CaseId))
    .AsEnumerable()                                 // Switch context
    .Select(x => new Case() {
        CaseId = x.CaseId,
        NotifierId = x.NotifierId,
        Notifier = x.NotifierId.HasValue
            ? new Notifier() { Name = x.Notifier.Name }
            : null
    })
    .ToList();

这将导致EF只生成一个SQL查询,直到你放置.AsEnumerable(),在此之后,LINQ to Objects将完成所有工作。这样做的好处是,您可以使用无法转换为SQL的代码,并且不需要对现有代码库进行大量更改(除非您使用了大量let表达式...)