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
相关产品推荐
相关产品推荐

