在Linq Select中创建一个元组

Van*_*nel 76 c# linq entity-framework tuples

我正在使用C#和.NET Framework 4.5.1使用Entity Framework 6.1.3从SQL Server数据库中检索数据.

我有这个:

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

当我运行它时,我收到此消息:

LINQ to Entities中仅支持无参数构造函数和初始值设定项.

我不知道我是如何创建元组的,因为我发现的所有例子大多都是这样的.

我试过这个:

codes = codesRepo.SearchFor(predicate)
      .Select(c => Tuple.Create(c.Id, c.Flag))
      .ToList();
Run Code Online (Sandbox Code Playgroud)

并得到此错误:

LINQ to Entities无法识别方法'System.Tuple`2 [System.String,System.Byte] Create [String,Byte](System.String,Byte)'方法,并且此方法无法转换为商店表达式.

问题出在哪儿?

Iva*_*oev 88

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

codes = codesRepo.SearchFor(predicate)
    .Select(c => new { c.Id, c.Flag })
    .AsEnumerable()
    .Select(c => new Tuple<string, byte>(c.Id, c.Flag))
    .ToList();
Run Code Online (Sandbox Code Playgroud)

  • @skyfrog 表达式树中不支持运算符 `?.`。但除此之外,您可以使用任意数量的值扩展匿名类型 - 只是不要忘记在需要时命名它们:) 例如`c =&gt; new { c.Id, c.Flag, Code = (int? )c.Foo.Code }` (2认同)

Raf*_*lin 31

只是C#7的更新答案,现在您可以使用更简单的语法来创建ValueTuples.

codes = codesRepo.SearchFor(predicate)
.Select(c => new { c.Id, c.Flag })
.AsEnumerable()
.Select(c => (c.Id, c.Flag))
.ToList();
Run Code Online (Sandbox Code Playgroud)

您甚至可以立即命名元组的属性:

codes = codesRepo.SearchFor(predicate)
.Select(c => new { c.Id, c.Flag })
.AsEnumerable()
.Select(c => (Id: c.Id, Flag: c.Flag))
.ToList();
Run Code Online (Sandbox Code Playgroud)

因此,您可以将其作为Id或Flag访问,而不是将其用作Item1或Item2.


Dhu*_*unt 10

试试这个:

codes = codesRepo.SearchFor(predicate)
  .Select(c => Tuple.Create(c.Id, c.Flag))
  .ToList();
Run Code Online (Sandbox Code Playgroud)

被告知这不是LINQ对实体的接受.

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

codes = codesRepo.SearchFor(predicate).AsEnumerable()
  .Select(c => Tuple.Create(c.Id, c.Flag))
  .ToList();
Run Code Online (Sandbox Code Playgroud)

如果你想在元组类型中使代码更明确一些,那么Tuple.Create(c.Id,c.Flag)也可以改为新的元组(c.Id,c.Flag)


oct*_*ccl 9

linq to实体中,您可以投影到匿名类型或DTO上.为了避免该问题,您可以使用AsEnumerable扩展方法:

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

这种方法可以让你一起工作的LINQ to对象,而不是LINQ到实体,所以称它为后,你可以提出查询无论你need.The使用的优势,结果AsEnumerable反而ToList被认为AsEnumerable不执行查询时,它保留了延迟执行.在调用其中一种方法之前,最好先过滤数据.


Van*_*nel 6

我找到了答案:

codes = codesRepo.SearchFor(predicate)
      .ToList()
      .Select(c => Tuple.Create(c.Id, c.Flag))
      .ToList();
Run Code Online (Sandbox Code Playgroud)