2015-11-05 35 views
34

我正在使用C#和.NET Framework 4.5.1使用Entity Framework 6.1.3从SQL Server数据库检索数据。在Linq Select中创建元组

我有这样的:

codes = codesRepo.SearchFor(predicate) 
     .Select(c => new Tuple<string, byte>(c.Id, c.Flag)) 
     .ToList(); 

当我运行它,我得到这个消息:

Only parameterless constructors and initializers are supported in LINQ to Entities.

我不知道我怎么要创建元组,因为所有的例子是我发现大多是这样的。

我已经试过这样:

codes = codesRepo.SearchFor(predicate) 
     .Select(c => Tuple.Create(c.Id, c.Flag)) 
     .ToList(); 

而得到这个错误:

LINQ to Entities does not recognize the method 'System.Tuple`2[System.String,System.Byte] Create[String,Byte](System.String, Byte)' method, and this method cannot be translated into a store expression.

问题出在哪里?

+0

看起来你需要创建一个强类型的对象。但是,是的,很好的问题; upvoted。 – frenchie

回答

38

虽然answer通过octavioccl的作品,这是最好的第一个项目的查询结果为匿名类型,然后切换到枚举并将其转换为元组。这样,您的查询将从数据库中仅检索所需的字段。

codes = codesRepo.SearchFor(predicate) 
    .Select(c => new { c.Id, c.Flag }) 
    .AsEnumerable() 
    .Select(c => new Tuple<string, byte>(c.Id, c.Flag)) 
    .ToList(); 
+0

非常好的解决方案 - 谢谢! ...如果我不得不通过另一个可为空的值来扩展此解决方案,怎么样? '.Select(c => new {c.Id,c.Flag,c.Foo?.Code})'不起作用。 – skyfrog

+1

@skyfrog表达式树中不支持运算符'?.'。但除此之外,您可以使用尽可能多的值扩展匿名类型 - 只是不要忘记在需要时为其命名:)例如'c => new {c.Id,c.Flag,Code =(int?)c.Foo.Code}' –

+1

太好了!非常感谢@Ivan的回复。我太亲近了! ...但回顾往往容易说出来;-) – skyfrog

9

试试这个:

codes = codesRepo.SearchFor(predicate) 
    .Select(c => Tuple.Create(c.Id, c.Flag)) 
    .ToList(); 

被告知这是不是在LINQ接受的实体。

另一种选择是在选择前将结果存入内存。如果你打算这样做,我会建议在.AsEnumerable()之前进行所有的过滤,因为这意味着你只需要返回你想要的结果,而不是拉回整个表,然后过滤。

codes = codesRepo.SearchFor(predicate).AsEnumerable() 
    .Select(c => Tuple.Create(c.Id, c.Flag)) 
    .ToList(); 

以及Tuple.Create(c.Id,c.Flag)可能被更改为新的元组(c.Id,c.Flag)如果你想使代码位的元组更明确类型

+0

对不起,它不起作用。我更新了我的问题,并提供了更多细节。 – VansFannel

+0

我做了一个编辑。 – Dhunt

7

linq to entities可以投影到匿名类型或到DTO.To避免这个问题,你可以使用AsEnumerable扩展方法:

codes = codesRepo.SearchFor(predicate).AsEnumerable(). 
     .Select(c => new Tuple<string, byte>(c.Id, c.Flag)) 
     .ToList(); 

此方法可以调用之后Linq to Object代替Linq to Entities工作,所以它可以投影结果在您需要的任何查询中。使用AsEnumerable而不是ToList的好处是AsEnumerable不会执行查询,它会保留延迟执行。在调用其中一种方法之前,总是先过滤数据是个好主意。

3

我已经找到了答案:

codes = codesRepo.SearchFor(predicate) 
     .ToList() 
     .Select(c => Tuple.Create(c.Id, c.Flag)) 
     .ToList(); 
0

使用此方法执行此操作并使用异步。

var codes = await codesRepo.SearchFor(predicate) 
        .Select(s => new 
        { 
         Id = s.Id, 
         Flag = s.Flag 
        }).FirstOrDefaultAsync(); 

       var return_Value = new Tuple<string, byte>(codes.Id, codes.Flag);