【问题标题】:LINQ ToDictionary System.InvalidCastException: 'Unable to cast object of type 'System.Int32' to type 'System.String'.'LINQ ToDictionary System.InvalidCastException:“无法将“System.Int32”类型的对象转换为“System.String”类型。
【发布时间】:2017-06-13 02:21:52
【问题描述】:

在这里发疯了,但是有一个我想转换为 Dictionary 对象的 LINQ 查询,但得到一个“System.InvalidCastException:'无法将'System.Int32'类型的对象转换为'System.String'类型。 '" 这样做时出错,所以我很难过。只有当我只想使用 Key 并使用 Product 类作为值时才会发生这种情况。

ProductsDataContext context = new ProductsDataContext();

Dictionary<int, Product> result = context.Products.Where(x => x.ProductName.StartsWith("N")).ToDictionary(x => x.Prod_ID); 

Prod_ID 是类和数据库中的整数。任何地方都不应该转换为字符串,所以我对这个错误消息感到困惑。

如果我这样写:

Dictionary<int, string> result = context.Products.Where(x => x.ProductName.StartsWith("N")).ToDictionary(x => x.Prod_ID, x=> x.ProductName)

它工作正常并且没有数据转换错误消息(Key 是指定的整数)。我以前没有使用过这种方法(w/LINQ to SQL),所以我认为缺少一些东西。 (它适用于非 SQL 的东西)

在不同的表上尝试了相同的代码并得到了结果(没有错误)。 看起来问题出在 Product 表中的空值(varchar() 空值 - 所以错误消息完全关闭 - 也许是一个错误?)

    StylesDataContext context = new StylesDataContext();

    Dictionary<int,Style> results = context.Styles.Select(x => x).Where(x => x.style_name.EndsWith("d")).ToDictionary(x => x.style_id);
    foreach (KeyValuePair<int, Style> r in results)
    {
        Console.WriteLine("id: " + r.Key.ToString()  + "\tName: " + r.Value.style_name + "\tGUID: " + r.Value.style_bvin  );
    }

【问题讨论】:

  • Product 中的一个变量可能是 int 但 linq 试图将其转换为字符串?我对来自 mysql 数据库的布尔值有类似的问题(它将它们存储为 1 和 0,通常很好,但对于一些 linq 查询,它拒绝正确进行转换)
  • 我怀疑使用ToList() 而不是ToDictionary 会在您的第一个查询中导致同样的错误。如果这是真的,则映射定义中有错误。
  • 尝试跟随:Dictionary> result = context.Products.GroupBy(x => x.ProductName.Substring(0,1)).ToDictionary(x => x.键,y => y.Prod_ID.ToList());错了三件事。 1)您的密钥是字符串而不是整数,因为它以字母开头。 2)由于多个产品可以以 N 开头,因此您的字典是一个列表。 3)你在构建字典时使用 GroupBy
  • 密钥是 DB 和 DBML 中的一个整数(并照此映射)(它是自动生成的,但我验证它是)。我没有进行任何类型的分组 - 内部查询返回一个 Product 列表。不确定在这种情况下分组是什么意思。我只是希望 prod_ID 成为 Key,Product 对象成为 Value。

标签: c# linq dictionary linq-to-sql


【解决方案1】:

试试下面的代码:

ProductsDataContext context = new ProductsDataContext();
var r1 = context.Products.Where(x => x.ProductName.StartsWith("N"));
var r2 = r1.ToDictionary(x => x.Prod_ID);

错误是发生在 r1 还是 r2 上?如果您使用 VS 保留变量名称以查看每个 var 语句使用的类型。产品的 Enumerable 似乎可能会产生错误。

【讨论】:

  • 第二行产生错误。现在我的第一个版本正在生成错误。 .ToDictionary(x => x.Prod_ID, x=> x.ProductName )
  • 好的。我选择了一个不同的表,查询基本上按照编写的方式工作,新表的唯一区别是任何地方都没有空值。另一个表在检索到的行中的某些 varchar() 列中有空值。
  • ProductName 属性是否可能是问题的根源?我在想有人将它编码为“返回字母+(字符串)数字”,其中“数字”被原型化为对象。另外我不知道你的 db 有多活跃,但是当你试图解决这样的问题时,你应该尝试使用静态数据来减少运行变化。
  • 我创建了一个新的 Product2 表并将 Product 表中的所有数据复制到其中,然后再次尝试。查询没有错误。相同的表,约束,一切。为了踢球,我再次尝试了旧查询,但失败了。然后,我删除了原始的 dbml 文件,并将其添加回来 - 旧查询不再产生错误。所以,不知何故,原始的、未经编辑的、自动生成的 DBML 文件本身就损坏了!啊!
  • 好吧,我猜如果它“不是”代码,那它一定是数据 :-) 很高兴你弄明白了。
【解决方案2】:

这个特定问题的答案是,不知何故,Visual Studio 2017 损坏了 LINQ-to-SQL 类的一部分自动生成的代码(我没有做过任何更改)。删除这些类并将它们添加回来解决了有关此查询的错误消息的问题。

我对数据已损坏或表中存在导致问题的空值的假设是不正确的。

我运行了一次硬盘扫描以查看我的 PC 上的数据是否损坏,但它恢复正常。

如果再次发生这种情况,我一定会逐个文件进行完整的比较,以查看实际损坏的部分并将其发布在此处和 MS 开发团队。如果这是一个错误,那就太糟糕了,浪费时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-25
    • 2020-05-16
    • 1970-01-01
    • 2019-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    相关资源
    最近更新 更多