MongoDB学习(翻译5)
C#驱动序列化文档对象
介绍
本文档基于C#官方驱动1.8版本。
本节C#驱动教程谈论C#类到BSON对象的序列化和反序列化。序列化是映射一个对象到可保存到MongoDB库中BSON对象的过程,反序列化由BSON文档重建对象的逆过程。因此,序列化过程通常被称为“对象映射”
序列化使用BSON库处理。BSON库拥有一个可扩展的序列化结构,所以你可以控制你的序列化方式。BSON库提供的默认的序列化其可以满足你大部分的需求,如果你需要特殊处理,你可以对其进行扩展。
默认序列化器通过“类映射”来处理。类映射是定义类和BSON文档对象间映射的一种结构,它包含一系列参与序列化的字段或属性并且为每一个定义了所需的序列化参数(例如,BSON元素名,代表选项等)。
默认的序列化器也内建了对.NET数据类型(原始类型、数组、集合、字典等)的支持。
序列化一个类对象之前,该类映射必须存在,可以手动创建类映射也可以简单的通过自动映射来创建。你可以在类自动映射的过程中通过使用序列化相关特性或者初始化代码的方式施加一些控制。
创建类映射
在你的初始化代码中创建类映射:
BsonClassMap.RegisterClassMap<MyClass>();
在此MyClass 会被自动映射或者注册,当然你可以让你的类通过序列化器自动映射。
如果你想控制创建的类映射,你可以在一个lambda表达式中提供您自己的初始化代码:
BsonClassMap.RegisterClassMap<MyClass)(cm => {
cm.MapProperty(c => c.SomeProperty);
cm.MapProperty(c => c.AnotherProperty);
});
当lambda表达式执行“CM”(简称类映射),参数传递一个空类映射供您填充。在本例子中两个属性通过调用MapProperty 方法被添加进去,传进MapProperty 的参数是它们本身。使用lambda表达式,而不是仅仅使用一个字符串参数的属性名称的优点是IntelliSense和编译时检查,确保你正确的拼写属性名称。
另外,也可以使用自动映射,然后覆写一些结果。稍后我们将会看到这方面的例子。
注意类映射必须只能被注册一次(如果你试着多次注册同一个类,会抛出异常)。
通常情况,你可以在只执行一次的代码路径中调用RegisterClassMap (Main 方法,Application_Start 事件等),如果你在执行次数多于一次的代码路径中调用RegisterClassMap 方法,你也可以通过调用IsClassMapRegistered 来检查该类是否被注册过:
if (!BsonClassMap.IsClassMapRegistered(typeof(MyClass))) {
// 为MyClass注册类映射
}
Creator Maps
默认情况下,类必定包括一个无参的构造函数来用于类的实例化,然后配置一个具有和映射属性相关的参数的构造函数是可以的,有两种方法可以实现:
使用一个表达式,你可以按照下面方式通过驱动使用一个creator map
public class Person
{
public string FirstName { get; private set; }
public string LastName { get; private set; }
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
}
BsonClassMap.RegisterClassMap<Person>(cm =>
{
cm.AutoMap();
cm.MapCreator(p => new Person(p.FirstName, p.LastName));
});
解析表达式树使构造函数第一个参数和FirstName 相关,使构造函数第二个参数和LastName 属性相关。还有其他更复杂的方式处理这种情况,当需要时,可以研究探索。
通过特性:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
[BsonConstructor]
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
}
当不止一个构造函数是,我们通过“满足大多数参数”这一策略来确定哪个是最好的匹配,例如:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime? BirthDate { get; set; }
[BsonConstructor]
public Person(string firstName, string lastName)
{
// snip...
}
[BsonConstructor]
public Person(string firstName, string lastName, DateTime birthDate)
{
// snip...
}
}
如果数据库中文档对象有一个BirthDate字段,我们会选择使用包含3个参数的构造函数,因为它更具体。
除了上面代码和属性的形式,映射一创建者可以通过约定(约束)来处理。
约定(约束)
自动进行类映射有许多需要考虑的方面,例如
. 例如
- 哪个字段或属性应该被序列化
- 哪个字段或属性是ID列
- 什么元素名称可以被用在BSON文档中
- 如果是多态,怎么确定使用哪个
- 如果我们无法识别一个BSON文档中包含的元素会如何
- 字段或属性是否有一个默认值
- 默认值应该被序列化还是被忽略
- null 值应该被序列化还是被忽略
这些问题的答案就代表一组约定。对于每一个约定都有一个默认的惯例,它是最有可能被您使用的一个,在必要时也可以重新个别约定(甚至写你自己的)。
如果你想使用和默认约定不同的自己的约定,可以很简单的创建一个ConventionPack 的实例,添加你想使用的约定进去,然后注册(换句话说,当你使用具体约定的时候通知序列化器)。例如:
var myConventions = new ConventionPack();
pack.Add(new CamelCaseElementNameConvention());
ConventionRegistry.Register(
"My Custom Conventions",
pack,
t => t.FullName.StartsWith("MyNamespace."));
第三个参数是用来定义何时使用这个约定包的过滤器方法。在这种情况下,也就是指如果任何类的全名以MyNamespace开头的话应该使用myConventions约定。
由上面我们已经了解到,除了预定的约定(约束),你可以自定义自己的约定(约束)。有4个可以让我们创建和注册自定义约定的类,运行在不同(阶段)级别。
- 类(阶段)级别: IClassMapConvention
运行针对类映射阶段.
- 方法(成员) 级别(阶段): IMemberMapConvention
运行针对在IClassMapConvention 阶段发现映射的每名成员
- Creator 阶段: ICreatorMapConvention
运行针对在IClassMapConvention 阶段发现映射的CreatorMap
- 后期处理阶段: IPostProcessingConvention
运行针对类映射阶段.
约定在他们注册的每个阶段顺序运行,默认的约定会先注册,这就允许任何用户注册的约定覆盖掉默认的约定。所以某些值可能得到应用和覆写,这就要求用户确保注册顺序的正确性。
注意:
如果一个IPostProcessingConvention 的自定义实现的注册早于一个IClassMapConvention的自定义实现,那么IClassMapConvention 先运行,因为它是运行类阶段是早于后处理阶段的。
待续。。。。
下篇介绍:
Field or Property Level Serialization Options
MongoDB学习(翻译5)的更多相关文章
- MongoDB学习3
MongoDB学习(翻译3) 支持的where字句(比较多,今天先写一部分) 本节介绍支持的where字句 正如前面提到的,不是所有的C#表达式都支持where子句.您可以以此文为指导,或者你可以 ...
- MongoDB学习2
MongoDB学习(翻译2) C#驱动之LINQ教程 介绍 本教程涵盖了1.8发布版本对linq查询的支持. 开始本教程之前,你应该至少阅读下C#驱动教程关于C#驱动的介绍 快速开始 首先,添加下面命 ...
- MongoDB学习笔记二- Mongoose
MongoDB学习笔记二 Mongoose Mongoose 简介 之前我们都是通过shell来完成对数据库的各种操作, 在开发中大部分时候我们都需要通过程序来完成对数据库的操作 而Mongoose就 ...
- MongoDB学习笔记系列
回到占占推荐博客索引 该来的总会来的,Ef,Redis,MVC甚至Sqlserver都有了自己的系列,MongoDB没有理由不去整理一下,这个系列都是平时在项目开发时总结出来的,希望可以为各位一些帮助 ...
- MongoDB学习笔记—Linux下搭建MongoDB环境
1.MongoDB简单说明 a MongoDB是由C++语言编写的一个基于分布式文件存储的开源数据库系统,它的目的在于为WEB应用提供可扩展的高性能数据存储解决方案. b MongoDB是一个介于关系 ...
- Mongodb学习笔记一(Mongodb环境配置)
Mongodb学习 说明: MongoDB由databases组成,database由collections组成,collection由documents组成,document由fileds组成.Mo ...
- MongoDB学习记录
一.操作符 "$lt" :"<""$lte" :"<=""$gt" :"> ...
- PHP操作MongoDB学习笔记
<?php/*** PHP操作MongoDB学习笔记*///*************************//** 连接MongoDB数据库 **////*************** ...
- MongoDB学习:(二)MongoDB简单使用
MongoDB学习:(二)MongoDB简单使用 MongoDB使用: 执行mongodb的操作之前,我们需要运行命令,来进入操作命令界面 >mongo 提示该错误,说明我们系统缺少一个补丁,该 ...
- MongoDB学习:(一)MongoDB安装
MongoDB学习:(一)MongoDB安装 MongoDB介绍: 直接百科了: MongoDB安装: 1:下载安装: MongoDB安装:https://www.mongodb.com/do ...
随机推荐
- 从头开始学JavaScript (五)——操作符(二)
原文:从头开始学JavaScript (五)--操作符(二) 一.乘性操作符 1.乘法:* 乘法操作符的一些特殊规则: 如果操作数都是数值,按照常规的乘法计算,如果乘积超过了ECMAscri ...
- 【BZOJ3450】【Tyvj1952】Easy 可能DP
联系: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网 ...
- NOIP 2012 解决问题的方法
[D1T1vigenerepassword] P1778vigenerepassword Accepted 标签:[显示标签] 描写叙述 16世纪法国外交家Blaise de Vigenère设计了一 ...
- iOS程序 # 启动过程
[ App 应用 ] 中文名:缺省 外文名:default 拼音:quē shěng 释义:系统默认状态 全称:缺省状态 -------------- 1.程序启动顺序 1> main.m程序入 ...
- 菜鸟学Java(二十一)——怎样更好的进行单元測试——JUnit
測试在软件生命周期中的重要性,不用我多说想必大家也都很清楚.软件測试有许多分类,从測试的方法上可分为:黑盒測试.白盒測试.静态測试.动态測试等:从软件开发的过程分为:单元測试.集成測试.确认測试.验收 ...
- vi使用高级
下面的命令在vi命令模式被激活 h 光标左移一个字符 l 光标向右移动一个字符 j 光标下移一行 k 移动光标线 一.对整行操作 1.复制光标所在行 yy 2.删除光标所在行 dd 3.选中光标所在行 ...
- Office 365 – Exchange Online examples
原文 Office 365 – Exchange Online examples 2012 is upon us and here’s wishing you all a very happy and ...
- C和Java中数组的定义
在学习C和Java中,关于数组的定义两者不同,在初学的时候,容易产生混淆,现在将两者对比下. 1.初始化 在C语言中,关于一维数组的定义: 完全初始化 int a[5]={1,2,3,4,5},对于 ...
- android:由URL载入中ImageView
两种方法: 方法一: Bitmap bimage= getBitmapFromURL(bannerpath); image.setImageBitmap(bimage); public static ...
- Zend server最大化应用程序的性能、扩展性和可用性
如果我有8个小时去砍到一棵树,我会花6个小时磨斧子”——林肯(美国总统) 你可以知道? 世界页面访问量的峰值超过7000万每分钟. CloudFare公司服务器问题,导致785000站点崩溃一小时. ...