【问题标题】:"InnerText" on XmlNode in LINQ query do not workLINQ 查询中 XmlNode 上的“InnerText”不起作用
【发布时间】:2009-06-26 08:42:39
【问题描述】:

当我在 LINQ 查询中调用 XmlNode 上的属性“InnerText”时,我收到一个奇怪的错误:“已添加具有相同键的项目。”。

查询如下:

var partnersXml = from partnerTable in dataContext.SomeTableInDb
                  where partnerTable.XmlType == "partner"
                  select new
                  {
                     partnerId = XmlDocumentWrapper(partnerTable.XmlDocument).SelectSingleNode("//*[name()='partnerId']").InnerText                 
                  };

解释:

  • partnerTable.XmlDocument 是 DB 中的字符串 xml
  • XmlDocumentWrapper 方法为给定的 xml 字符串返回一个 XmlDocument

在没有“InnerText”的情况下查询可以完美运行(然后 partnerId 包含 XmlNode)。这是 LINQ 中的某种错误还是什么?这个问题的解决方法是什么?

堆栈跟踪:

System.ArgumentException:已添加具有相同键的项目。 在 System.ThrowHelper.ThrowArgumentException(ExceptionResource 资源) 在 System.Collections.Generic.Dictionary2.Insert(TKey key, TValue value, Boolean add) at System.Data.Linq.Mapping.UnmappedType.GetDataMember(MemberInfo mi) at System.Data.Linq.SqlClient.SqlFactory.Member(SqlExpression expr, MemberInfo member) at System.Data.Linq.SqlClient.QueryConverter.VisitMemberAccess(MemberExpression ma) at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node) at System.Data.Linq.SqlClient.QueryConverter.Visit(Expression node) at System.Data.Linq.SqlClient.QueryConverter.VisitExpression(Expression exp) at System.Data.Linq.SqlClient.QueryConverter.VisitNew(NewExpression qn) at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node) at System.Data.Linq.SqlClient.QueryConverter.Visit(Expression node) at System.Data.Linq.SqlClient.QueryConverter.VisitSelect(Expression sequence, LambdaExpression selector) at System.Data.Linq.SqlClient.QueryConverter.VisitSequenceOperatorCall(MethodCallExpression mc) at System.Data.Linq.SqlClient.QueryConverter.VisitMethodCall(MethodCallExpression mc) at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node) at System.Data.Linq.SqlClient.QueryConverter.ConvertOuter(Expression node) at System.Data.Linq.SqlClient.SqlProvider.BuildQuery(Expression query, SqlNodeAnnotations annotations) at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) at System.Data.Linq.DataQuery1.System.Collections.Generic.IEnumerable.GetEnumerator()

【问题讨论】:

  • 任何堆栈跟踪?你在做任何分组吗?清楚的?听起来好像在某处涉及字典......
  • 没有分组,没有区别。我得到的唯一消息是“已添加具有相同密钥的项目。”

标签: c# linq


【解决方案1】:

看起来 LINQ to SQL 正在尝试进行一些映射,而您希望它在 .NET 端完成。 (我假设 - 如果您希望数据库执行 XPath,恐怕我不知道。)试试这个:

var partnersXml = dataContext.SomeTableInDb
     .Where(x => x.XmlType == "partner")
     .AsEnumerable() // This forces the rest of the query to be done in the CLR
     .Select(x => new {
          partnerId = XmlDocumentWrapper(x.XmlDocument)
                           .SelectSingleNode("//*[name()='partnerId']")
                           .InnerText
     });

【讨论】:

  • 乔恩,很好的解决方案。我会在伦敦的 StackOverflow 开发日上请你喝啤酒。 :) 关键是“.AsEnumerable()”,不需要使用 lambda 表达式来查询它。它也可以像从 dataContext.SomeTableInDb.AsEnumerable() 中的 partnerTable 一样完成。
  • 您不希望在 SQL 中执行“where”子句吗?您需要计算出您希望在 SQL 中发生多少查询,以及您希望在 CLR 中发生多少。
  • 是的,我想要,但我只是举了一个例子,如果你想要非 lambda 查询如何解决这个问题。但正如在 SQL 中运行 where 子句一样,几乎总是更好的想法(性能)是您的 lambda 解决方案完美。
  • 你仍然可以在没有任何 lambda 表达式的情况下在 SQL 中运行 where 子句,但它会涉及两个查询表达式,而且很丑;)
  • 谢谢乔恩!我刚刚遇到了类似的问题,但有同样的异常,这解决了它。
猜你喜欢
  • 1970-01-01
  • 2018-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多