使用官方 C# 驱动程序与 MongoDB 结合使用






4.87/5 (27投票s)
介绍如何使用官方 C# 驱动程序在 ASP.NET MVC 项目中使用 MongoDB。
引言
MongoDB 是 NoSQL 世界中一个引人注目的应用,它通过驱动程序、全面的文档和相当大的社区提供了大量支持,可以用于构建使用 NoSQL 技术的应用程序,而不是直接转向 MS SQL Server 和 Oracle 等关系数据库管理系统。
在本文中,我想介绍如何使用官方 C# 驱动程序来使用 MongoDB。这个驱动程序有一些替代方案,其中一些甚至被认为更好,提供了额外的功能,如 LINQ 支持,但我更喜欢在我的项目中使用这个驱动程序,因为它得到了官方支持。
代码示例取自演示项目。我建议您仔细研究演示项目,因为这样您会理解得更好,并且可以选择尝试 MongoDB。
关于 MongoDB 数据结构的一些说明
在 MongoDB 中,数据结构和层次结构如下:
Databases
Collections
Documents
Fields
字段是键值对。键是名称(字符串)。值是基本类型,如字符串、整数、浮点数、时间戳、二进制等,或者是一个文档,或者是一个值数组。
简而言之,集合是由类 JSON 文档组成的。这是与传统关系数据库管理系统最大的区别,因此请尝试将您的数据视为真实对象,而不是纯数据。此外,您将在官方驱动程序中看到以 Bson
开头的类。
bsonspec.org 对 BSON 的定义是 JSON 类文档的二进制编码序列化。BSON 被设计成轻量级、可遍历且高效。BSON 就像 JSON 一样,支持在其他对象和数组中嵌入对象和数组。
准备工作
首先,从以下地址下载合适的 MongoDB 包并执行 mongod.exe 来启动您的 MongoDB 服务器。
如果您在启动服务器时遇到与路径相关的问题,请创建一个文件夹来存储数据库文件,并使用 dbpath 参数启动 mongod.exe,将文件夹路径作为以下行所示给出:
mongod.exe --dbpath "C:\data"
为了使用此驱动程序,请从以下链接下载所需的程序集文件:
在这里,您可以获取源代码并下载安装包。当您下载了合适的包并安装它后,您就可以在 Program Files Folder\MongoDB\CSharpDriver 1.2 路径下找到以下两个程序集文件。顺便说一下,我在本文中使用了 CSharpDriver-1.2.0.4274.msi。
- MongoDB.Bson.dll
- MongoDB.Driver.dll
您需要将这两个文件作为引用添加到您的项目中。MongoDB.Bson.dll 用于 BSON 序列化,另一个用于数据库通信。现在,您已准备好使用 MongoDB 开发您的项目。
服务器启动
首先,您应该确保 MongoDB 正在运行,并且您指向服务器正在运行的端口是正确的。下面您可以看到从命令行启动 MongoDB 服务器时的输出。
在屏幕上,端口用红色框标出。然后,通过运行 mongo.exe 启动 MongoDB 控制台,并运行以下行来创建您的数据库:
use MessageDB
现在您已完成 MongoDB 服务器的设置。
Application
我们将使用这两个命名空间来与我们的 MongoDB 服务器和数据进行通信和处理,所以请添加以下行:
using MongoDB.Driver;
using MongoDB.Bson;
// Create server settings to pass connection string, timeout, etc.
MongoServerSettings settings = new MongoServerSettings();
settings.Server = new MongoServerAddress("localhost", 27017);
// Create server object to communicate with our server
MongoServer server = new MongoServer(settings);
// Get our database instance to reach collections and data
var database = server.GetDatabase("MessageDB");
在这些行中,我们创建一个服务器对象,并传入所需的设置,如凭据、连接字符串、端口等。在此示例中,我们使用 localhost 作为数据库服务器,27017 作为服务器端口。然后,我们访问之前创建的数据库 MessageDB。有了数据库对象,我们就可以进行 CRUD 操作了。
读取
var users = database.GetCollection("users").
FindAll().
SetSortOrder(SortBy.Descending("createdate"));
官方驱动程序提供了多种访问和处理数据的方式。在上面的行中,我们首先使用 createdate 值按顺序访问 users
集合。也可以通过索引 [] 访问集合或其他兼容集合,例如 datasase["users"]
。
foreach (var user in users)
{
var userName = user["firstname"].AsString;
...
}
在获取结果(无论是 BSON 格式还是强类型对象格式)后,我们可以对其进行迭代。
可以使用 Query
编写复杂的查询。
var query = Query.And(
Query.Matches("firstname", BsonRegularExpression.Create("^e")),
Query.GT("createdate", BsonValue.Create(DateTime.Now.AddDays(-7).Date)));
// Get all users whose firstname starts with 'e' and who are
// created within last 7 days in sorted format by createdate
var users = database.
GetCollection("users").
Find(query).
SetSortOrder(SortBy.Descending("createdate"));
您可以通过如下方式获取从对象转换为 MongoDB 表示的查询:
编辑
当我们获取数据时,我们可以直接编辑值,并通过调用相关集合的 Save
方法来保存更新的文档。在以下行中,我们通过提供 ID 值来获取一个唯一文档。
// Update user by id
var user = users.FindOneById(ObjectId.Parse(id));
user["firstname"] = userToEdit.FirstName;
user["lastname"] = userToEdit.LastName;
user["age"] = userToEdit.Age;
// Update user object
users.Save(user);
ID 值是一种特殊类型的字段,由数据库本身创建,以确保每个文档的唯一性,因此可以轻松获取文档。ID 值实际上包含一个字符串值,如 4ea41ac244b8681c3072b212,因此可以轻松地通过每次请求传递此值。
FindOneById
方法接收一个 BsonValue
。为了将 ID 值作为 BsonValue
传递,我们调用 ObjectId.Parse
来获取 ID 值适合的 BsonValue
格式。
最后,我们调用 Save
来更新编辑后的文档。
插入
添加新文档和编辑文档一样简单。您创建一个集合的引用,创建一个新的 BsonDocument
,并通过调用 insert
将其添加到集合引用中。
// Get user collection reference
var users = database.GetCollection("users");
// Create BsonDocument object for new user
var user = new BsonDocument();
user["firstname"] = userToEdit.FirstName;
user["lastname"] = userToEdit.LastName;
user["age"] = userToEdit.Age;
user["createdate"] = DateTime.Now;
// Insert new user object to collection
users.Insert(user);
动态模式
到目前为止,我们考虑了基本对象,并对它们进行了 CRUD 操作。正如您所见,我们还没有定义任何特定的模式设置。当我们在 BsonDocument
中设置一个值时,字段键会根据给定值的类型自动创建。在以下情况下,当我们执行以下行时:
user["age"] = 18;
age
键会自动创建,字段类型将是 Int32
。您还可以通过调用对象的 Contains
方法来检查键是否存在,并确保它与给定类型兼容并且可以正确转换,例如:
if (user.Contains("updatedate") && user["updatedate"].IsDateTime)
{
var updatedate = user["updatedate"].AsDateTime;
}
我提到了动态模式,我想让我的用户对象更具动态性。
[HttpPost]
public ActionResult Index(string id, string newRemark)
{
var users = database.GetCollection("users");
var user = users.FindOneById(ObjectId.Parse(id));
var remark = new BsonDocument().
Add("content", newRemark).
Add("date", DateTime.Now);
if (user.Contains("remarks"))
{
user["remarks"].AsBsonArray.Add(BsonValue.Create(remark));
}
else
{
user["remarks"] = new BsonArray().Add(BsonValue.Create(remark));
}
users.Save(user);
return RedirectToAction("Index", new { id = id });
}
在这些行中,我们更改了用户对象。我们提出了新的数据类型 remarks
。
首先,我们检查用户对象是否已包含键为 remarks
的元素。remarks
实际上是一个数组,其中包含 content
和 date
值。如果 remarks
存在,我们将其转换为数组并添加一条新备注。否则,我们创建一个新的数组类型并添加新备注。仅此而已。用户对象的输出将是这样的:
{
"_id" : ObjectId("4ea51941073d601758138560"),
"firstname" : "ercan",
"lastname" : "anlama",
"age" : 26,
"createdate" : ISODate("2011-10-24T07:52:33.29Z"),
"remarks" :
[
{
"content" : "this is my first remark",
"date" : ISODate("2011-10-24T07:53:22.511Z")
}
]
}
对象序列化
驱动程序支持对象的序列化为文档。这意味着您不需要使用字符串值来访问字段和值,而是可以使用强类型值。让我们实际看看。
我们有两个对象:User
和 Remark
。
public class User
{
public User()
{
Remarks = new List<Remark>();
}
public ObjectId id { get; set; }
[BsonElementAttribute("firstname")]
public string FirstName { get; set; }
[BsonElementAttribute("lastname")]
public string LastName { get; set; }
[BsonElementAttribute("age")]
public int Age { get; set; }
[BsonElementAttribute("createdate")]
public DateTime CreateDate { get; set; }
[BsonElementAttribute("remarks")]
public IList<Remark> Remarks { get; set; }
public string GetFullName()
{
return String.Format("{0} {1}", FirstName, LastName);
}
}
public class Remark
{
[BsonElementAttribute("content")]
public string RemarkContent;
[BsonElementAttribute("date")]
public DateTime Date;
}
我们使用 BsonAttribute
来指定对象中的哪个属性与 BsonDocument
中的哪个字段匹配。另外,请注意,我们定义了一个特殊的属性,即 ObjectId
类型,用于存储 BsonDocument
的 ID 值。如果属性名称与字段键相同,则无需指定任何属性,就像我们在 id
属性中所做的那样。
以下是实现此序列化的方法:
var user = database.GetCollection("users").FindOneByIdAs<User>(ObjectId.Parse(id));
驱动程序使用以 As
结尾的方法。通常,这些方法用于以强类型格式检索文档。因此,我们可以保持 NoSQL 数据与面向对象之间的桥梁。
最后的寄语
我试图在本文中介绍 MongoDB 是什么以及如何使用官方 C# 驱动程序。当然,这些只是基本内容,但却是 MongoDB 最常用的功能,所以它比本文所展示的要广泛得多。它提供了强大的功能,如 GridFS 和 MapReduce,您在开发 MongoDB 项目的某些领域可能需要用到它们。