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

MongoDB C#/.NET Driver:UUID与ISODate反序列化异常求助

问题描述

MongoDB集合中的文档如下:

{
  _id: new UUID("31daac77-bcbc-4cd5-bb93-382440f46f16"),
  CompanyId: 'XYZ',
  RequestDate: ISODate("2023-01-10T07:52:32.840Z")
}

对应的C#实体类:

public class ReportRequest
{
    public ReportRequest(string companyId)
    {
        this.Id = Guid.NewGuid();
        this.CompanyId = companyId;
        this.RequestDate = DateTime.UtcNow;
    }

    [BsonId]
    [BsonElement("_id")]
    [BsonGuidRepresentation(GuidRepresentation.Standard)]
    public Guid Id { get; }

    [BsonElement]
    public string CompanyId { get; }

    [BsonElement]
    [BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
    public DateTime RequestDate { get; }
}

查询代码:

public async Task PrintAvailableReportDatesAsync(string companyId)
{
    var filter = Builders<ReportRequest>.Filter.Eq(r => r.CompanyId, companyId);
    var cursor = await _collection.FindAsync(filter);
    var reportRequests = await cursor.ToListAsync();

    foreach (var req in reportRequests)
        Console.WriteLine($"Id: {req.Id.ToString()}, Date: {req.RequestDate}");
}

期望输出:

Id: 31daac77-bcbc-4cd5-bb93-382440f46f16, Date: 2023-01-10T07:52:32.840Z

实际输出:

Id: 00000000-0000-0000-0000-000000000000, Date: 0001-01-01T00:00:00

问题原因

你的ReportRequest类中所有属性都只有只读的getter(get;),没有setter。MongoDB .NET驱动在反序列化文档到实体类时,需要能够设置这些属性的值,但当前的只读属性无法被驱动赋值,所以只能使用类型的默认值(Guid默认是全0,DateTime默认是0001-01-01)。

修正方案

有几种可行的修正方式:

方式1:添加私有setter

给每个属性添加私有setter,这样驱动可以通过反射访问私有成员来赋值,同时保持外部代码无法修改属性:

public class ReportRequest
{
    public ReportRequest(string companyId)
    {
        this.Id = Guid.NewGuid();
        this.CompanyId = companyId;
        this.RequestDate = DateTime.UtcNow;
    }

    [BsonId]
    [BsonElement("_id")]
    [BsonGuidRepresentation(GuidRepresentation.Standard)]
    public Guid Id { get; private set; }

    [BsonElement]
    public string CompanyId { get; private set; }

    [BsonElement]
    [BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
    public DateTime RequestDate { get; private set; }
}

方式2:使用C# 9+的init关键字

如果使用C# 9及以上版本,可以用init代替私有setter,它允许在对象初始化时赋值,之后属性变为只读:

public class ReportRequest
{
    public ReportRequest(string companyId)
    {
        this.Id = Guid.NewGuid();
        this.CompanyId = companyId;
        this.RequestDate = DateTime.UtcNow;
    }

    [BsonId]
    [BsonElement("_id")]
    [BsonGuidRepresentation(GuidRepresentation.Standard)]
    public Guid Id { get; init; }

    [BsonElement]
    public string CompanyId { get; init; }

    [BsonElement]
    [BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
    public DateTime RequestDate { get; init; }
}

方式3:添加无参构造函数(配合私有setter)

如果驱动需要无参构造函数(旧版本驱动可能有此要求),可以添加私有无参构造函数,同时保留私有setter:

public class ReportRequest
{
    private ReportRequest() { } // 供驱动反序列化使用

    public ReportRequest(string companyId)
    {
        this.Id = Guid.NewGuid();
        this.CompanyId = companyId;
        this.RequestDate = DateTime.UtcNow;
    }

    [BsonId]
    [BsonElement("_id")]
    [BsonGuidRepresentation(GuidRepresentation.Standard)]
    public Guid Id { get; private set; }

    [BsonElement]
    public string CompanyId { get; private set; }

    [BsonElement]
    [BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
    public DateTime RequestDate { get; private set; }
}

内容的提问来源于stack exchange,提问作者Brian Reading

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 11:10:14