Overview
在本指南中,您可以学习;了解如何自定义MongoDB .NET/ C#驱动程序将BSON文档与C#类相互映射的方式。要学习;了解有关默认类映射行为的更多信息,或者是否必须自定义驾驶员序列化或反序列化数据的方式,请阅读此页面。
您还可以使用 POCO 属性来设立序列化行为。要学习;了解详情,请参阅 POCO指南。
自动类映射
当您使用类而非 BsonDocument
表示MongoDB集合中的数据时,.NET/C#驱动程序会自动创建一个类映射,用于序列化或反序列化您的数据。它通过将文档中的字段名称与类中的属性名称进行匹配来完成此映射。
重要
将类中的属性类型与文档中的字段类型相匹配。.NET/ C#驱动程序根据类中属性的类型实例化序列化器。如果驾驶员尝试反序列化数据时类型不匹配,则序列化程序会引发异常。
手动创建类映射
您可以绕过驱动程序的自动类映射功能,并使用 RegisterClassMap()
方法手动定义类映射。
以下示例定义 Person
类:
public class Person { public string Name { get; set; } public int Age { get; set; } public List<string> Hobbies {get; set;} }
以下代码演示如何注册 Person
类的类映射:
BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.MapMember(p => p.Name); classMap.MapMember(p => p.Age); classMap.MapMember(p => p.Hobbies); });
重要
何时注册类映射
您必须先注册类映射,然后才能在代码中使用它。我们建议在初始化与MongoDB 的连接之前注册类映射。
您还可以手动映射类属性的子集,同时仍允许驱动程序自动映射其余属性。为此,注册类映射并调用 AutoMap()
方法,然后再手动指定属性。
在以下代码示例中,AutoMap()
方法映射 Person
类的所有属性,然后手动调整 Hobbies
字段的映射:
BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.AutoMap(); classMap.MapMember(p => p.Hobbies).SetElementName("favorite_hobbies"); });
自定义类序列化
您可以通过对类应用属性或在注册类映射时调用方法来自定义驾驶员在类级别序列化和反序列化文档的方式。
省略字段
您可以在注册类映射时使用 UnmapMember()
方法来防止指定字段被序列化。
以下示例展示了如何创建类映射以防止 Age
属性被序列化:
BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.AutoMap(); classMap.UnmapMember(p => p.Age); });
提示
要了解如何通过字段属性设置此行为,请参阅 POCO 指南中的省略字段部分。
忽略额外元素
当 BSON 文档反序列化为 C# 类时,.NET/C# 驱动程序会查看文档中每个字段的名称,并尝试在类中查找匹配的属性名称。默认情况下,如果文档中的字段在类中没有匹配项,驱动程序会抛出异常。
您可以使用 BsonIgnoreExtraElements
属性选择忽略任何没有匹配类属性的元素。这样可以防止驱动程序抛出异常,并映射具有匹配类属性的任何其他字段。
以下示例显示如何将 BsonIgnoreExtraElements
属性添加至类。
[ ]public class Person { public string Name { get; set; } public int Age { get; set; } public List<string> Hobbies {get; set;} }
您还可以在注册类映射时忽略任何额外元素:
BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.AutoMap(); classMap.SetIgnoreExtraElements(true); });
识别 Id 字段
默认情况下,驱动程序会将名为 Id
、id
或 _id
的任何公共属性映射到 BSON _id
字段。要明确选择映射到 _id
字段的属性,请使用 MapIdMember()
类映射方法。
以下代码示例将 Identifier
属性映射到 _id
字段:
BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.AutoMap(); classMap.MapIdMember(p => p.Identifier); });
字符串 ID
如果您使用字符串来表示文档 ID,可以使用 IdMemberMap.SetSerializer()
类的 map 方法将这些值序列化为 MongoDB 中的 ObjectId
实例。这样,您可以自定义 ID 值在您的应用程序中的表示方式,同时遵循 MongoDB 数据库中 ID 管理的最佳实践。
以下示例指示驱动程序将字符串 ID 值序列化为 ObjectId
值:
BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.AutoMap(); classMap.IdMemberMap.SetSerializer(new StringSerializer(BsonType.ObjectId)); });
如果您希望驱动程序生成有效的 24 位十六进制字符串作为您的 ID 值,您可以将 SetIdGenerator()
方法链接到 MapIdMember()
方法,并传递一个 StringObjectIdGenerator
的实例:
BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.AutoMap(); classMap.MapIdMember(p => p.Identifier).SetIdGenerator(StringObjectIdGenerator.Instance); });
要了解有关 ID 生成器的更多信息,请参阅 POCOs 指南的指定 ID 生成器部分。
GUID ID
如果您的应用程序使用 GUID 作为文档中的唯一标识符,您可以注册类映射以指定如何序列化 Guid
值。默认情况下,驱动程序使用 GuidGenerator
类型为 ID 属性生成唯一的值。您必须通过初始化 GuidSerializer
来指定 GUID 表示。
以下代码在注册类映射时指定 Standard
GUID 表示形式:
BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.AutoMap(); classMap.IdMemberMap.SetSerializer(new GuidSerializer(GuidRepresentation.Standard)); });
要学习;了解有关序列化 GUID 的更多信息,请参阅 GUID 指南。
使用构造函数映射
默认情况下,仅当类具有不带参数的构造函数时,.NET/C# 驱动程序才能自动映射该类。如果想要驱动程序使用接受一个或多个参数的构造函数,您可以将 BsonConstructor
属性添加到该构造函数中。在这种情况下,驱动程序会检查类型以确定如何将构造函数参数映射到类属性或字段。
当驱动程序为以下 Person
类创建类映射时,它将使用标有 BsonConstructor
属性的构造函数。name
参数将映射到 Name
属性,并且 age
参数将映射到 Age
属性。
public class Person { public string Name { get; set; } public int Age { get; set; } public List<string> Hobbies {get; set;} [ ] public Person(string name, string age) { Name = name; Age = age; } }
提示
多个 BsonConstructor 属性
如果存在多个具有 BsonConstructor
属性的构造函数,则驱动程序将使用具有与文档中匹配字段的最多参数的构造函数。
您还可以指定注册类映射时要使用的构造函数:
public class Person { public string Name { get; set; } public int Age { get; set; } public List<string> Hobbies {get; set;} public Person(string name, string age) { Name = name; Age = age; } } BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.AutoMap(); classMap.MapCreator(p => new Person(p.Name, p.Age)); });
自定义属性序列化
您可以通过向类属性中添加多个属性来自定义驱动程序序列化类属性的方式。有关自定义属性序列化的更多信息,请参阅自定义序列化。
支持额外元素
您可以设计 C# 类来存储文档中没有匹配类属性的任何额外元素。为此,您的类必须具有 BsonDocument
类型属性以保存额外的元素。
以下代码使用带有 ExtraElements
类属性的 BsonExtraElements
属性来指示驱动程序存储额外元素:
public class Person { public string Name { get; set; public int Age { get; set; } public List<string> Hobbies {get; set;} [ ] public BsonDocument ExtraElements {get; set;} }
在初始化类映射时,还可以支持额外元素,如下所示:
BsonClassMap.RegisterClassMap<Person>(classMap => { classMap.AutoMap(); classMap.MapExtraElementsMember(p => p.ExtraElements); });
注意
驱动程序将带有额外元素的类序列化回 BSON 后,额外元素的顺序可能与原始文档中的顺序不同。
动态序列化属性
您可以使用一种方法来确定是否序列化属性。为了使驾驶员在序列化时自动使用该方法,您必须在方法名称前加上 ShouldSerialize
作为前缀,后跟该方法所适用的属性的名称。当驾驶员看到具有此命名约定的方法时,它会使用该方法来确定是否序列化具有所提供属性名称的属性。
以下示例创建一个仅在其值不等于 0
时序列化 Age
属性的方法。驱动程序不会序列化其值不满足此要求的任何属性:
public class Person { public string Name { get; set; } public int Age { get; set; } public List<string> Hobbies {get; set;} public bool ShouldSerializeAge() { return Age != 0; } }
您还可以在注册类映射时指定方法:
BsonClassMap.RegisterClassMap<Employee>(classMap => { classMap.AutoMap(); classMap.MapMember(p => c.Age).SetShouldSerializeMethod( obj => ((Person) obj).Age != 0 ); });
更多信息
有关使用 C# 类的更多信息,请参阅 POCO。