将 Linq 查询结果转换为字典
Posted
技术标签:
【中文标题】将 Linq 查询结果转换为字典【英文标题】:Convert Linq Query Result to Dictionary 【发布时间】:2010-10-31 12:49:55 【问题描述】:我想使用 Linq to SQL 向数据库添加一些行,但我想在添加行之前进行“自定义检查”以了解是否必须添加、替换或忽略传入的行。 我想保持客户端和数据库服务器之间的流量尽可能低,并尽量减少查询次数。
为此,我想获取验证所需的尽可能少的信息,并且只在流程开始时获取一次。
我正在考虑做这样的事情,但显然,它不起作用。有人有想法吗?
Dictionary<int, DateTime> existingItems =
(from ObjType ot in TableObj
select (new KeyValuePair<int, DateTime>(ot.Key, ot.TimeStamp))
)
我最后想要的是一个字典,而不必从 TableObject 下载整个 ObjectType 对象。
我也考虑了以下代码,但我试图找到一个合适的方法:
List<int> keys = (from ObjType ot in TableObj orderby ot.Key select ot.Key).ToList<int>();
List<DateTime> values = (from ObjType ot in TableObj orderby ot.Key select ot.Value).ToList<int>();
Dictionary<int, DateTime> existingItems = new Dictionary<int, DateTime>(keys.Count);
for (int i = 0; i < keys.Count; i++)
existingItems.Add(keys[i], values[i]);
【问题讨论】:
【参考方案1】:尝试像这样使用the ToDictionary
method:
var dict = TableObj.Select( t => new t.Key, t.TimeStamp )
.ToDictionary( t => t.Key, t => t.TimeStamp );
【讨论】:
@pawan,它是枚举中每个元素的占位符,并采用枚举中对象的类型。 @pawan - 看起来不对。我希望var servers = list.Select( s => new s.ProjectName, Url = "tcp://" + s.BuildMachineName + ":" + s.PortNumber + "/CruiseManager.rem" ).ToDictionary( s => s.ProjectName, s.Url );
这会创建一个以项目名称/url 对的项目名称为键的字典。
为什么.Select( t => new t.Key, t.TimeStamp )
表达式是必要的?
@BenCollins:我认为中间的.Select
会导致生成的SQL只选择Key和TimeStamp,而不是选择每一列。
如果你正在使用 Linq to Object(而不是 Linq to SQL),你可以省略这个中介 Select
【参考方案2】:
看看你的例子,我认为这就是你想要的:
var dict = TableObj.ToDictionary(t => t.Key, t=> t.TimeStamp);
【讨论】:
哇...可能就这么简单...由于我对编程很陌生,我会尝试一下并进行一些分析以确保在幕后,我不会获得整个对象的命中。我会及时通知你。 我刚刚完成了我的检查。可悲的是,在获取 TableObj 时,它从数据库中获取了所有对象,所以我最终得到了流量。我还检查了我发布的第二种方式(并希望避免)的查询,他们只得到了必要的项目。当然它会执行 2 次查询,因此服务器本身必须搜索两次表,但对象映射很简单。 你也许可以这样做:TableObj.Select(t => new t.Key, t.TimeStamp ).ToDictionary(t => t.Key, t => t.TimeStamp) ; LinqToSql 应该能够注意到您只想要两件事(来自选择)并返回它们。我不确定深入研究 ToDictionary() 的细节是否足够聪明。 不错!这是结果查询:SELECT [t0].[Key], [t0].[TimeStamp] FROM [TableObj] AS [t0]。我不想因此而受到赞扬,所以继续将其发布为anwser! :-P【参考方案3】:试试下面的
Dictionary<int, DateTime> existingItems =
(from ObjType ot in TableObj).ToDictionary(x => x.Key);
或完全成熟的类型推断版本
var existingItems = TableObj.ToDictionary(x => x.Key);
【讨论】:
感谢 JaredPar 的回答。我教过类似的东西,但我认为这会返回 ObjType 类型的整个对象,并且我想避免下载整个对象。 @Tipx,你能提供一些关于你想要过滤的信息吗?添加过滤子句是可能的,但我无法从你的问题中看出什么是重要的 我只需要知道是否需要添加、忽略或替换另一行的“新行”就是对象的时间戳。数据库中的对象有很多我不需要验证的字段,我不想获得获取整个对象的性能影响。为了简单起见,我在我的 BD 中有一个包含 20 列、100 000 行的表,我想使用前 2 列的值提取字典。 我刚刚检查了该代码生成的服务器查询,您可能知道,它获取了整个对象。【参考方案4】:使用命名空间
using System.Collections.Specialized;
创建DataContext
类的实例
LinqToSqlDataContext dc = new LinqToSqlDataContext();
使用
OrderedDictionary dict = dc.TableName.ToDictionary(d => d.key, d => d.value);
为了检索值使用命名空间
using System.Collections;
ICollection keyCollections = dict.Keys;
ICOllection valueCollections = dict.Values;
String[] myKeys = new String[dict.Count];
String[] myValues = new String[dict.Count];
keyCollections.CopyTo(myKeys,0);
valueCollections.CopyTo(myValues,0);
for(int i=0; i<dict.Count; i++)
Console.WriteLine("Key: " + myKeys[i] + "Value: " + myValues[i]);
Console.ReadKey();
【讨论】:
对于 多个键 ?以上是关于将 Linq 查询结果转换为字典的主要内容,如果未能解决你的问题,请参考以下文章