2011-05-29 215 views
0

我知道实体框架有一些LINQ支持问题(至少与其前身LINQ to SQL相比)......通常我可以找到重构我的LINQ查询的创造性方式它支持EF并且不抛出一个实体框架复杂LINQ支持

"Unable to create a constant value of type ..." 

但是这次我遇到了麻烦。像往常一样,这个问题与复杂的连接有关。这次我们需要对一些我正在使用的遗留数据进行建模。

我有办事处查询(一个简单的POCO)

public IQueryable<Office> Offices 
{ 
    get 
    { 
     IQueryable<Office> query = 
      from pn in _context.Locations 
      where pn.Type == "Y" 
      select new Office 
      { 
       Id = pn.Id + 1000, 
       Name = pn.Name, 
      }; 

     query = query.Union(
      from r in _context.Resources 
      where r.ResourceType == "L" 
      select new Office 
      { 
       Id = r.ResourceId, 
       Name = r.ResourceName, 
      }); 

     return query; 
    } 
} 

然后,我有别的东西上有一个写字楼物业。

public IQueryable<ScheduleEntry> ScheduleEntries 
{ 
    get 
    { 
     return 
      from pc in _context.CalendarEntries 
      join o in this.Offices on pc.LocationId 
       equals o.Id into offices 
      from office in offices.DefaultIfEmpty() 
      let mainOffice = this.Offices.First() 
      select new ScheduleEntry 
      { 
       Id = pc.CalendarId, 
       StartDateTime = pc.StartDateTime ?? DateTime.MinValue, 
       EndDateTime = pc.EndDateTime ?? DateTime.MinValue, 
       Office = pc.LocationId == 0 ? mainOffice : office, 
      }; 
    } 
} 

请注意,告诉我使它成为一个枚举失败的目的......所以请不要提醒。

等等....做CalendarEntries.ToArray()抛出"Unable to create a constant value of type Office"...

具体问题是let mainOffice = Offices.First()。如果我删除该逻辑,查询工作正常。任何想法如何使这个工作与实体框架?

谢谢。

+2

哇。 “可怜的LINQ支持?”我认为你应该把这个问题关闭的情绪或风险编辑为主观和论证。坚持这一点。 – 2011-05-29 01:35:35

+2

EF没有差的linq支持。它不依赖于商店。 Linq to sql基本上是一个SQL Server代码生成,而EF是一个真正的ORM。这意味着只有在任何数据存储(不只是SQL Server)中有办法执行它们时,计算的属性才会起作用。这不是不好的支持,只是通用的数据存储支持。 – Gats 2011-05-29 01:42:18

+0

这听起来更像是一个威胁,而不是一个建议。虽然公平,但我正在寻求帮助,而不是威胁。 – Jeff 2011-05-29 01:43:06

回答

2

好的,看起来像双查询是绊倒它。唯一的选择是要么离开加盟办公室或执行以下操作:

 Office mainOffice = Offices.First(); 
     return from pc in _context.CalendarEntries 
       join o in Offices on pc.LocationId equals o.Id into offices 
       from office in offices.DefaultIfEmpty() 
       select new ScheduleEntry 
          { 
           Id = pc.CalendarId, 
           StartDateTime = pc.StartDateTime ?? DateTime.MinValue, 
           EndDateTime = pc.EndDateTime ?? DateTime.MinValue, 
           Office = pc.LocationId == 0 ? mainOffice : office, 
          }; 

我假设你不想做,由于对使它IEnumerable的投诉,所以你需要加入到办事处可查询一些如何告诉EF如何将查询串起来。让x = y或者value = value寻找一个我认为有意义的常量。

+0

我得到相同的“无法创建类型...的常量值”异常。 – Jeff 2011-05-29 02:34:35

+0

看了更深,编辑的建议。对不起,我试图回答自己的问题,并且陷入了这个问题:D – Gats 2011-05-29 02:44:44

+0

谢谢。我得到同样的错误这样做...但是,如果我得到的主要办公室Id前期:var mainOfficeId = Offices.First()。Id,然后使用该ID在查询中的第二个连接,它的工作....它是不理想,但它的工作原理。 – Jeff 2011-05-29 02:45:46

0

First在构建表达式树时执行查询,以便尝试将Office作为参数传递给您的查询,但无法完成。

取代First的一种方法是呼叫this.Offices.Take(1)

+0

这也会产生相同的“无法创建常量值类型”错误。另外 - 如果表达式树是大型表达式树的一部分,则首先不执行查询。也就是说,在我提供的原始示例中,它是作为Method First的MethodCallExpression创建的......它不会在构建时直接执行。 – Jeff 2011-05-29 14:17:02

+0

@Jeff:我刚刚在另一个查询上测试了First,并且一旦我在子查询中使用它,我得到一个异常:*'First'方法只能用作最终的查询操作。考虑在这个例子中使用方法'FirstOrDefault'。*所以我仍然认为'First'不能在查询中使用,但'FirstOrDefault'可以。 – 2011-05-29 14:23:12

+0

好点!...但这仍然是EF提供者的一个功能,而不是表达式树的创建方式。我只是尝试用FirstOrDefault()替换First()中的First(),我仍然得到相同的“无法创建常量值...”异常... – Jeff 2011-05-29 14:34:26