实体或复杂类型…不能在LINQ to Entities查询中构造

为什么一个方法可以工作而另一个方法不工作,因为它们似乎都在做同样的事情,即构建一个实体。 那么我的问题是,有没有办法在L2E查询中构造实体,而不是只使用Linq或两者兼而有之?

这很好……

var queryToList = (from ac in ctx.AuthorisationChecks where wedNumbers.Contains(ac.WedNo) orderby ac.WedNo, ac.ExpAuthDate, ac.ActAuthDate select new AuthorisationCheck { Blah = ac.Blah }).ToList(); model.AuthorisationChecks = queryToList.Select(x => new AuthorisationCheck { Blah = x.Blah }).ToList(); 

但是,如果我改变……

 var queryToList 

 model.AuthorisationChecks queryToList // Of type List 

我在标题中得到错误…

 The entity or complex type 'Model.AuthorisationCheck' cannot be constructed in a LINQ to Entities query. 

编辑:在模型中它很简单,没有什么花哨的。

 public List AuthorisationChecks { get; set; } 

编辑2:整理一下(这很好)…

 model.AuthorisationChecks = (from ac in ctx.AuthorisationChecks where wedNumbers.Contains(ac.WedNo) orderby ac.WedNo, ac.ExpAuthDate, ac.ActAuthDate select ac).ToList() .Select(x => new AuthorisationCheck { Blah = x.Blah }).ToList(); 

EDIT2:我的解决方案我对匿名类型方法不满意,所以继续创建一个只包含我需要在viewmodel中使用的属性的简单模型。

改变了模型的类型。授权检查

 List // List of Entities 

 List // List of models 

它允许以下代码工作,并且没有分析它似乎比使用匿名类型快得多(当然我不会两次转换为列表!)。

 model.AuthorisationChecks = (from ac in ctx.AuthorisationChecks where wedNumbers.Contains(ac.WedNo) orderby ac.WedNo, ac.ExpAuthDate, ac.ActAuthDate select new AuthorisationCheckModel { Blah = x.Blah }).ToList(); 

PS我曾经被一位同事(曾经为微软工作过)警告说,以这种方式直接使用实体并不是一个好主意,也许这是他想到的原因之一,我也注意到了一些在其他情况下直接使用实体的奇怪行为(主要是腐败)。

如果此查询正常工作:

 var queryToList = (from ac in ctx.AuthorisationChecks where wedNumbers.Contains(ac.WedNo) orderby ac.WedNo, ac.ExpAuthDate, ac.ActAuthDate select new AuthorisationCheck { Blah = ac.Blah }).ToList(); 

那么这也应该有效:

 model.AuthorisationChecks = (from ac in ctx.AuthorisationChecks where wedNumbers.Contains(ac.WedNo) orderby ac.WedNo, ac.ExpAuthDate, ac.ActAuthDate select new AuthorisationCheck { Blah = ac.Blah }).ToList(); 

在第一种情况下,您不需要再次投影,您可以直接将其分配给模型propeerty:

 model.AuthorisationChecks = queryToList; 

更新:

因为它是Linq To Entities,你必须使用匿名类型做这样的事情:

 var queryToList = (from ac in ctx.AuthorisationChecks where wedNumbers.Contains(ac.WedNo) orderby ac.WedNo, ac.ExpAuthDate, ac.ActAuthDate select new { Blah = ac.Blah }).ToList(); 

然后:

 model.AuthorisationChecks = queryToList.Select(x => new AuthorisationCheck { Blah = x.Blah }).ToList(); 

注意:我通常使用lambda表达式而不是Fluent API,但根本问题应该是相同的。

我曾经注意到, 如果 通过将查询转换为SQL来访问 原始数据源 (即ctx ), LINQ无法将C#类用于Select语句。

换句话说,从数据库中获取内容并将其转换为同一链中的自定义类时会出现问题。

LINQ足够聪明,它实际上不会立即执行链式调用。 它只是在内部构建一个查询,当您实际访问结果(即从内存中检索值)时,它会执行查询。
我认为这也是你遇到这个错误的原因,因为LINQ将所有内容(包括Select)转换为SQL,并且因为没有SQL方式来表达它而失败。 简而言之,LINQ无法做半个SQL的半嵌入式查询。 它全部在SQL中,或全部在代码中。

您通常可以通过首先创建数据库表的List<>然后对其运行完全相同的查询来确认是这种情况。

 var myTable = db.AuthorizationCheck.ToList(); var myResult = myTable. //query here 

注意:这不是解决方案!
将整个表放在内存中是一种过于密集的方法来解决这个问题。 它只是certificate了如果数据源在内存中就不会遇到问题,但如果它在数据库中就会发生错误。

有一些方法我已经解决了这个问题,虽然我从来没有找到一种统一的方法来解决这个问题(通常取决于我的代码审查员的意见,他是否喜欢修复)

使用匿名类型 ,您可以选择所需的内容,然后将其强制转换为正确的类。 您可以使用完全相同的字段,以便稍后理解。

 //Simpler query for clarity's sake var myAnonymousResult = ctx.AuthorizationChecks .Where(x => x.IsActive) .Select(x => new { Name = x.Name, IsActive = x.IsActive }) .ToList(); var myCastResult = myAnonymousResult.Select(x => new Check() { Name = x.Name, IsActive = x.IsActive }).ToList(); 

如果使用lambda表达式而不是流畅的API ,则可以应用filter之后但调用.Select()方法之前调用.ToList() 。 这确保了当前查询将被执行,从数据库中检索,并放入内存中的实际List<> 。 此时,您可以调用.Select()语句而不会遇到同样的问题。

 //Simpler query for clarity's sake var myCastResult = ctx.AuthorizationChecks .Where(x => x.IsActive) .ToList() .Select(x => new Check() { Name = x.Name, IsActive = x.IsActive }); 

不幸的是,我对这个问题的经验是轶事。 我从来没有能够正式确认我对这个问题的根本原因的怀疑; 但我提到的变通方法应该可行,因为我过去曾多次应用它们。

如果有人对根本原因有解释,我会非常有兴趣听到它!