You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB .NET Driver:筛选查询中字符串转DateTime报错的解决方法

问题

我有一个MongoDB酒店预订集合,其中包含字段:

public string CreationDate { get; set; }
// 其余字段已省略

我尝试检索两个日期范围内的酒店预订列表,单独执行日期转换逻辑正常,但在Filter、Where、Find查询中使用DateTime.ParseExact将CreationDate转为DateTime时均失败:

Filter方式代码

startDate = DateTime.ParseExact(Start + " " + "00:00:00", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); // 此代码正常运行

endDate = DateTime.ParseExact(End + " " + "00:00:00", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);  // 此代码正常运行

var filter = Builders<HotelBookingDocument>.Filter.Gt(s => (DateTime.ParseExact(s.CreationDate + " " + "00:00:00", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture)), startDate);

filter &= Builders<HotelBookingDocument>.Filter.Lt(s => (DateTime.ParseExact(s.CreationDate + " " + "00:00:00", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture)), endDate);

return await HotelBookingCollection.Find(filter).ToListAsync();  // 此代码无法运行

Where方式代码

query = await HotelBookingCollection.AsQueryable().Where(s => (
                      DateTime.ParseExact(s.CreationDate + " " + "00:00:00", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture) <= endDate)
                ).ToListAsync();

Find方式代码

query = await HotelBookingCollection.Find(s => (
                     startDate <= DateTime.ParseExact(s.CreationDate + " " + "00:00:00", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture))
                ).ToListAsync();

所有查询都会抛出如下错误:

System.InvalidOperationException: 
Unable to determine the serialization information for s => ParseExact(((s.CreationDate + " ") + "00:00:00"), "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture).

解决方法

方案1:修改实体类字段类型(推荐)

直接将CreationDate字段改为DateTime类型,MongoDB驱动可直接处理日期的序列化与反序列化,同时能利用日期索引提升查询性能,从根源避免字符串转日期的问题。

修改实体字段:

public DateTime CreationDate { get; set; }

查询代码简化为:

var filter = Builders<HotelBookingDocument>.Filter.Gte(s => s.CreationDate, startDate) 
           & Builders<HotelBookingDocument>.Filter.Lte(s => s.CreationDate, endDate);

var result = await HotelBookingCollection.Find(filter).ToListAsync();

方案2:转换查询日期为字符串格式匹配

若无法修改实体类,可将startDate和endDate转为与CreationDate一致的字符串格式(需确保日期字符串为yyyy-MM-dd这类字典序与时间顺序一致的格式),直接进行字符串范围查询。

示例代码:

// 假设CreationDate格式为"yyyy-MM-dd"
string startDateStr = Start; // Start为传入的"yyyy-MM-dd"格式字符串
string endDateStr = End;

var filter = Builders<HotelBookingDocument>.Filter.Gte(s => s.CreationDate, startDateStr)
           & Builders<HotelBookingDocument>.Filter.Lte(s => s.CreationDate, endDateStr);

var result = await HotelBookingCollection.Find(filter).ToListAsync();

方案3:使用聚合管道在数据库层转换日期

利用MongoDB的$dateFromString操作符,在聚合管道中完成字符串到日期的转换,让驱动能正确解析查询逻辑。

示例代码:

var pipeline = new BsonDocument[]
{
    new BsonDocument("$addFields", new BsonDocument(
        "convertedCreationDate", new BsonDocument(
            "$dateFromString", new BsonDocument
            {
                { "dateString", new BsonDocument("$concat", new BsonArray { "$CreationDate", "T00:00:00" }) },
                { "format", "%Y-%m-%dT%H:%M:%S" }
            }
        )
    )),
    new BsonDocument("$match", new BsonDocument(
        "$and", new BsonArray
        {
            new BsonDocument("convertedCreationDate", new BsonDocument("$gte", startDate)),
            new BsonDocument("convertedCreationDate", new BsonDocument("$lte", endDate))
        }
    ))
};

var result = await HotelBookingCollection.Aggregate<HotelBookingDocument>(pipeline).ToListAsync();

内容的提问来源于stack exchange,提问作者hanushi-thana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 18:55:17