无法在 MongoDB 的 LINQ 查询中将字符串转换为 int

问题描述 投票:0回答:2

因此,我正在执行 SelectMany 查询来迭代集合中对象内部的列表。这是我的查询:

var collection = _database.GetCollection<VehicleDataUpload>(VehiclesCollection);
var aggregation = collection.AsQueryable()
    .SelectMany(v => v.VehicleEntries)
    .Where(i => Convert.ToInt32(i.PostFlashDTCs) > 0)
    .ToList();

但是,每次运行此命令时都会出现以下错误:

MongoDB.Driver.dll 中发生了“System.InvalidOperationException”类型的第一次机会异常

我认为问题与转换函数有关,所以我将其更改为:

.Where(i => Convert.ToInt32("1") > 0)

而且效果仍然很好。我的同事说转换字符串 0 时可能会卡住,但是当我在

"0"
中进行硬编码时,它仍然有效。由于某种原因,它无法转换类字段。我已将该字段设置为字符串,甚至为其设置了默认值:

public class VehicleEntry
{
    [BsonElement("PostFlashDTCs")]
    [BsonDefaultValue("0")]
    public String PostFlashDTCs { get; set; }
}

当我从对象本身读取时,它显示 InvalidFormatException 的原因是什么?

编辑

我编写了一个快速的 for 循环来迭代(在删除 where 步骤之后)并打印是否存在无法转换为整数的字符串。控制台上没有打印任何内容:

foreach (VehicleEntry vehicle in aggregation1)
{
    int result;
    if (!Int32.TryParse(vehicle.PostFlashDTCs, out result))
    {
        Console.WriteLine("Bad value!");
    }
}

编辑2

我对查询进行了一些限制,以便从只有 12 个 VehicleEntry 元素的案例中提取。之后我放置了一个调试器(我暂时删除了 where 情况)并检查了所有 12 个元素,它们都具有 PostFlashDTCs 字段的有效数字字符串,因此问题在于转换函数,而不是无效字符串。

编辑3

如果我无法在 LINQ 查询中使用

Convert.ToInt32
,为什么当我对字符串值进行硬编码时它会正常工作?编译器是否做了一些奇怪的事情来优化该代码?我不知道这样的优化,但我认为这是可能的。

c# mongodb linq
2个回答
2
投票

mongo 驱动程序采用构建为表达式树的 linq 表达式,并将其转换为 Mongo 自己的本机查询语言。错误的原因是它不知道如何转换Convert.ToInt32。

.ToList() 部分强制查询在 Mongo 上运行,之后 linq 语句将在应用程序中运行,并且您将能够在 .ToList 之后使用 Convert.ToInt32。

您也许可以使用强制转换 (https://jira.mongodb.org/browse/CSHARP-900) 所以...

.Where(i => (int)i.PostFlashDTCs > 0)

如果没有向 Mongo 团队提票。


0
投票

所以...我有点陷入兔子洞的深处了。

如果您转到

MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToPipelineTranslators.ExpressionToPipelineTranslator
,您将看到
Mongo.Driver
能够将哪些方法转换为 Mongo 查询。尽管
Parse
是其中之一,但它仅解析为
DateTime
(
MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.MethodTranslators.ParseMethodToAggregationExpressionTranslator
):

    public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
    {
        if (expression.Method.Is(DateTimeMethod.Parse))
        {
            return TranslateDateTimeParse(context, expression);
        }
        throw new ExpressionNotSupportedException(expression);
    }

我的解决方案是使用

CompareTo
而不将
string
解析为
int
,而是将
int
常量转换为
string

var aggregation = collection.AsQueryable()
    .SelectMany(v => v.VehicleEntries)
    .Where(i => i.PostFlashDTCs.CompareTo("0") > 0)
    .ToList();
© www.soinside.com 2019 - 2024. All rights reserved.