简体   繁体   English

通过 EF / Linq 投射到 KeyValuePair

[英]Projecting into KeyValuePair via EF / Linq

I'm trying to load a list of KeyValuePairs from an EF / Linq query like this:我正在尝试从 EF / Linq 查询加载 KeyValuePairs 列表,如下所示:

return (from o in context.myTable 
select new KeyValuePair<int, string>(o.columnA, o.columnB)).ToList();

My problem is that this results in the error我的问题是这会导致错误

"Only parameterless constructors and initializers are supported in LINQ to Entities." “实体的 LINQ 中仅支持无参数构造函数和初始值设定项。”

Is there an easy way around this?有没有简单的方法解决这个问题? I know I could create a custom class for this instead of using KeyValuePair but that does seem like re-inventing the wheel.我知道我可以为此创建一个自定义 class 而不是使用 KeyValuePair 但这看起来确实像是在重新发明轮子。

Select only columnA and columnB from your table, and move further processing in memory: 从表中仅选择columnA和columnB,并在内存中移动进一步处理:

return context.myTable
              .Select(o => new { o.columnA, o.columnB }) // only two fields
              .AsEnumerable() // to clients memory
              .Select(o => new KeyValuePair<int, string>(o.columnA, o.columnB))
              .ToList();

Consider also to create dictionary which contains KeyValuePairs: 还要考虑创建包含KeyValuePairs的字典:

return context.myTable.ToDictionary(o => o.columnA, o => o.columnB).ToList();

Since LINQ to Entities does not support KeyValuePair , you should turns to LINQ to Object by using AsEnumerable first: 由于LINQ to Entities不支持KeyValuePair ,因此您应首先使用AsEnumerable转向LINQ to Object:

return context.myTable
              .AsEnumerable()
              .Select(new KeyValuePair<int, string>(o.columnA, o.columnB))
              .ToList();

With recent versions of EF Core selecting into KeyValuePair appears to work fine.使用最新版本的 EF Core 选择 KeyValuePair 似乎工作正常。 I also verified that (on MS SQL Server) the SQL only selects the two relevant fields, so the "Select" is actually translated:我还验证了(在 MS SQL 服务器上)SQL 只选择了两个相关字段,所以“选择”实际上是翻译的:

return context.myTable 
    .Select(x => new KeyValuePair<int, string>(o.columnA, o.columnB))
    .ToList();

SELECT [m].[columnA], [m].[columnB]
FROM [myTable] AS [m]

The generated SQL is the same as for anonymous classes, except that renames are only made for the latter ("eg AS A"):生成的 SQL 与匿名类相同,只是重命名仅为后者(“例如 A”):

return context.myTable 
    .Select(x => new {A = o.columnA, B = o.columnB})
    .ToList();

SELECT [m].[columnA] AS [A], [m].[columnB] AS [B]
FROM [myTable] AS [m]

Tested with .NET 6.用 .NET 6 测试。

Note that using a Dictionary (as suggested in other answers) will introduce additional constraints compared to a List of KeyValuePairs:请注意,与 KeyValuePairs 列表相比,使用字典(如其他答案中所建议的那样)会引入额外的约束:

  • The order of Dictionary entries is undefined.字典条目的顺序未定义。 Thus, while one (currently) typically has the same order of elements for filling in and enumerating over a Dictionary, this is not guaranteed (I've already seen cases of reordering) and might change without notice in the future.因此,虽然一个(当前)通常具有相同的元素顺序来填充和枚举字典,但这并不能保证(我已经看到重新排序的情况)并且将来可能会更改,恕不另行通知。
  • The key values in a Dictionary must be unique (which may or may not apply to columnA in the database, and would cause an exception if columnA is not).字典中的键值必须是唯一的(这可能适用于也可能不适用于数据库中的 columnA,如果 columnA 不是,则会导致异常)。
  • Dictionary does not allow "null" for the key (This is just for completeness, since the OP uses "int" type for the key anyway).字典不允许键为“null”(这只是为了完整性,因为 OP 无论如何都使用“int”类型作为键)。
  • The Dictionary keeps an index of its keys, so setting it up might take longer than just having a list of KeyValuePairs (though this is micro-optimisation...) Dictionary 保留其键的索引,因此设置它可能比仅拥有 KeyValuePairs 列表花费更长的时间(尽管这是微优化......)

Depending on the use case of the OP (which I cannot deduce from the question), some of these constraints might be desirable, though, and the Dictionary might actually be the solution.根据 OP 的用例(我无法从问题中推断出),其中一些约束可能是可取的,而 Dictionary 实际上可能是解决方案。

There is also alternative, when you want to store multiple values for one key exists something what is called Lookup . 还有另一种选择,当你想为一个键存储多个值时,存在一个叫做Lookup的东西。

Represents a collection of keys each mapped to one or more values. 表示每个映射到一个或多个值的键集合。

Here you have some official documentations . 这里有一些官方文件

More over lookup seems to be much faster than Dictionary < TKey, List < TValue > >. 更多的查找似乎比Dictionary <TKey,List <TValue >>快得多

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM