天天看點

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

閱讀目錄

​​開始​​

​​下載下傳MongoDB,并啟動它​​

​​在C#使用MongoDB​​

​​重構(簡化)代碼​​

​​使用MongoDB的用戶端檢視資料​​

​​使用MongoDB的用戶端維護資料​​

​​MongoDB提供的C#驅動​​

​​MongoDB不支援在查詢資料庫時使用Join操作​​

​​擷取MongoDB服務端狀态​​

【目标】:本文将以實戰的形式,向您展示如何用C#通路MongoDB,完成常見的資料庫操作任務, 同時,也将介紹MongoDB的用戶端(指令行工作模式)以及一些基礎的指令。

【說明】:MongoDB是什麼?有什麼用?如果不清楚這些問題的,請自己google一下吧。

【适合對象】:完全沒有接觸MongoDB或對MongoDB有一點了解的C#開發人員。是以本文是一篇入門級的文章。

【示例項目】:本文的完整示例是一個簡單的【客戶,商品,訂單】業務場景, ​​預覽界面效果請點選此處(但并不完全相同),也包含下載下傳示例項目的源碼。​​

讓我們開始MongoDB的實戰入門吧。

​​回到頂部​​

下載下傳MongoDB,并啟動它

您可以在這個位址下載下傳到MongoDB: ​​http://www.mongodb.org/downloads​​, 本文将以【mongodb-win32-i386-1.8.2-rc2】來示範MongoDB的使用。

下載下傳好了嗎?我們繼續吧。請解壓縮您剛才下載下傳的MongoDB的zip壓縮包,進入解包的bin目錄,會發現有一堆exe檔案。 現在,請打開指令行視窗并切換到剛才的bin目錄,然後輸入以下指令:

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

這裡,我運作了程式mongod.exe,并告訴它資料檔案的儲存目錄(這個目錄要事先建立好),至于mongod的更多指令行參數,請輸入指令: mongod /? 來獲得。 如果您也看到了這個界面,那麼表示MongoDB的服務端已成功啟動了。

順便提一下:運作mongod後,它會顯示一些有用的資訊。比如:pid (程序ID), tcp port (監聽端口), http 端口(用于檢視運作狀态), 作業系統版本,資料目錄,32 or 64位版本,如果是32位版本,它還會告訴你【資料有2G的限制】,是以正式使用建議運作64位版本。

接下來,我們還要去下載下傳MongoDB的C#驅動,它可以讓我們在C#中使用MongoDB 。下載下傳位址: ​​https://github.com/samus/mongodb-csharp​​ 我下載下傳到的壓縮包是:samus-mongodb-csharp-0.90.0.1-93-g6397a0f.zip 。這個壓縮包本身也包含了一個Sample,有興趣的可以看看它。 我們在C#通路MongoDB所需的驅動就是項目MongoDB了。編譯這個項目就能得到了,檔案名:MongoDB.dll

在C#使用MongoDB

好了,有了前面的準備工作,我們可以開始在C#中使用MongoDB了。不過,由于本示例項目的代碼也不少,是以本文将隻展示與MongoDB互動的相關代碼, 更完整的代碼請自行查閱示例項目。

接下來,本文示範通過C#完成【客戶資料】的一些基本的資料操作,還是先來定義一個客戶資料的類型吧。

說明:這就是一個簡單的類,而且代碼中的[MongoId]也是可以不要的(這個後面再說)。

在操作資料庫之前,我要說明一下:MongoDB在使用前,并不要求您事先建立好相應的資料庫,設計資料表結構! 在MongoDB中,沒有【表】的概念,取而代之的是【集合】,也沒有【資料記錄】的概念,取而代之的是【文檔】, 我們可以把【文檔】了解成一個【對象】,任意的對象,甚至可以有複雜的嵌套層次。 是以,我們不用再寫代碼從【資料表字段】到C#類的【屬性,字段】的轉換了,現在直接就可以讀寫整個對象了。 而且MongoDB不支援Join操作,是以,如果有【關聯】操作,就需要你自己來處理。

再來定義二個變量:

上面的代碼中,每一行都有注釋,這裡就不再解釋了。

重構(簡化)代碼

從上面代碼可以看出,操作MongoDB大緻都是這樣一個操作過程。

針對這個問題,我提供一個包裝類來簡化MongoDB的使用。

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

簡化後的CRUD代碼如下:

看了上面這些代碼,您應該會覺得MongoDB的使用也很容易,對吧。 接下來,我來通過界面錄入一些資料,來看看我錄入的結果吧。

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

到這裡,你或許想知道:MongoDB有沒有一個自己的用戶端來檢視資料呢?因為總不能隻依賴自己寫代碼來檢視資料吧? 是的,MongoDB也提供了一個用戶端來檢視并維護資料庫。接下來,我們再來看看如何使用MongoDB的用戶端吧。

使用MongoDB的用戶端檢視資料

MongoDB自帶一個Javascript shell,它可以從指令行與MongoDB執行個體互動。這個shell非常有用,通過它可以管理操作、檢查運作執行個體、查詢資料等操作。  讓我們再回到指令行視窗模式下吧(沒辦法,MongoDB隻提供這種界面),運作mongo.exe ,如下圖

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

這就是MongoDB的用戶端的指令行模式了。通常我們在操作資料庫前,要切換【目前資料】, MongoDB也是一樣,我們可以運作如下指令來檢視資料庫清單,并切換資料庫,然後再檢視集合清單,請看下圖(我運作了三條指令)

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

注意:MongoDB區分名字的大小寫。

在MongoDB中,檢視【目前資料庫】,可以使用指令【db】, 檢視集合Customer的記錄總數:【db.Customer.count();】 檢視 CustomerId = 1 的記錄:【db.Customer.findOne({"_id" : "1"});】,注意:查詢條件是一個文檔,這就是MongoDB的特色。 下圖顯示了上面三條指令的執行結果:

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

嗯,怎麼有亂碼?CustomerId = 1 的記錄應該是這樣的才對呀?

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

看到這一幕,您應該不要懷疑是MongoDB的錯了,這個錯誤是由于MongoDB的用戶端使用的編碼是UTF-8, 而Windows 指令行程式 cmd.exe 使用的gb2312(我目前使用中文語言) 造成的。 解決辦法: 1. 執行MongoDB的【exit】指令退回到Windows指令行狀态(或者重新打開指令行視窗), 2. 運作指令:【chcp 65001】,切換到UTF-8編碼下工作。 3. 設定指令行視窗的屬性,請參考下圖:

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

再運作 mongo 進入mongo指令行,切換資料庫,并執行指令:【db.Customer.findOne({"_id" : "1"});】

現在可以看到漢字能正常顯示了,但最後卻顯示"Failed to write to logfile",對于這個問題,我們如果執行指令 【db.Customer.findOne({"_id" : "91"});】(id=91的記錄就是我最後錄入的,全是a的那條,前面截圖上有), 可以發現沒有任何異常發生,是以認為這個問題還是和cmd.exe有關的。 如果切換回 chcp 936 ,這時将看到亂碼,但沒有"Failed to write to logfile",是以我将忽略這個錯誤。

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

使用MongoDB的用戶端維護資料

下面我來示範一下如何使用MongoDB的用戶端來執行一些基本的資料維護功能。還是從CRUD操作開始吧,請看下圖,為了友善,我将在一個截圖中執行多個指令。 注意:MongoDB的文檔使用的是一種稱為BSON格式的對象,與Javascript中的JSON類似。

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

在上面的示例中,每個指令後,我加了一個紅圈。在示例中,我先切換到 MyTest 資料庫(它并不存在,但沒關系), 然後我定義了一個文檔 item 并插入到集合 table1 中,然後又定義了一個文檔 item2,也插入到集合 table1 中。 注意:item , item2 的結構完全不同,但能放在一個集合中(不建議這樣做)。最後調用 find() 顯示集合中的所有文檔。 此時,您有沒有注意到:【每個文檔有一個名為 "_id" 的成員】,我可沒有定義啊。 其實,MongoDB會為每個文檔都建立這樣一個文檔成員,我們指定的 "key", "id" 對于MongoDB來說: 它們并不是【文檔的主鍵】,MongoDB隻認 "_id",你可以指定,但如果不指定,MongoDB就自動添加。

此時,你可以看看前二張圖檔,可以發現:在定義Customer類時,有一個成員CustomerID此時卻不存在! 我們可以再看一下Customer的定義:

此時,您應該發現CustomerID這個成員有一個[MongoId]的特性。正是由于這個特性,驅動程式将把CustomerID映射為"_id"來使用。

好了,再次回到指令行,我要示範其它的指令。請看下圖:

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

為了要更新某個文檔,我們要使用findOne()方法找到要修改的文檔對象,并将它儲存一個變量t中,然後,修改它的屬性, 接着調用update()方法就可以更新文檔了,注意在調用update()時,第一個參數【更新範圍】是采用文檔的形式給出的, 第二參數才是要更新的新對象。在删除時,删除條件也是采用文檔的形式指定的。處處使用文檔,這就是MongoDB的特色。

前面的示例代碼中,我使用了find()和findOne(),它們是有差別的:findOne()隻傳回一個文檔對象,find()傳回一個集合清單, 如果不指定過濾範圍,它将傳回整個集合,但在用戶端中最多隻顯示前20個文檔。

再來個複雜的查詢:搜尋日期範圍是 2011-06-25 到 2011-06-26 之間的訂單記錄。由于傳回的結果太長,我的截圖将不顯示它們。 注意:MongoDB的查詢條件中,并沒有 >, <, >= , <= 這些運算符,而是使用 "$lt", "$lte", "$gt", "$gte" 這種方式作為文檔的KEY來使用的, 是以一個簡單的 OrderDate >= "2006-06-25" and OrderDate < "2006-06-26" 要寫成如下方式:

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

如果遇到 or 就更麻煩了,如:CustomerId = 1 or CustomerId = 2 ,有二種寫法:

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

文法不難,相信能看懂JSON的人,也能看懂這二條指令。

再來個分頁的指令:

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

與LINQ的文法類似,好了解。

MongoDB用戶端還支援其它的文法,這裡就不一一介紹了。因為我們的目标是在C#中使用MongoDB,在MongoDB提供的C#驅動中, 我們并不需要寫那樣麻煩的查詢條件,隻需要按LINQ的文法寫查詢就可以了,是以會很容易使用。 不過,有些維護性的操作,我們隻能通過指令的方式去執行,比如:删除集合,删除資料庫。

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

執行【db.runCommand({"drop" : "table1"});】便可以删除一個集合,也可以執行指令【db.table1.drop();】,二者的效果是一樣的。 再來看看如何删除資料庫的指令:

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

注意:指令【db.runCommand({"dropDatabase": 1});】隻能删除【目前資料庫】,是以要先切換目前資料庫, 然後執行這個指令,執行删除資料庫的指令後,我們再用指令【show dbs;】,發現資料庫【MyTest】已不存在,即删除成功。 删除資料庫還有一個方法:還記得我前面啟動mongod.exe時給它傳遞了一個參數 【-dbpath "H:\AllTempFiles\mongodb\data"】嗎? 我們現在去那個目錄看一下有什麼東西。

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

看了這張圖,您有沒有想過:這二個以【MyNorthwind】開頭的檔案會不會就是資料庫的檔案呢? 我現在就删除看看,先停止mongod.exe,然後删除檔案(由于我目前隻有一個資料庫,我把目錄下的檔案全删除了),删除後:

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

現在,我再來啟動mongod.exe,然後在用戶端執行指令【show dbs;】看看:

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

現在可以發現我們之前的【MyNorthwind】資料庫沒有了,當然也就是删除了。 說明一下:現在這二個資料庫,是MongoDB自帶的,用于特殊用途的,我們可以不理會它們。

好了,我們還是再來看看MongoDB提供的C#驅動提供了什麼東西吧。

MongoDB提供的C#驅動

我把MongoDB提供的C#驅動中認為比較重要的類做了個截圖:

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

再來看看我前面給出一段操作MongoDB的代碼:

這段代碼大緻也說明了在C#中操作MongoDB的一個過程,主要涉及上圖中的前三個類,這三個類也是最核心的類。 這裡值得一提的是:LinqExtensions.Linq()方法可以讓我們在寫查詢時, 友善地使用LINQ的優雅文法,而不是一堆複雜的文檔條件!這也是我選擇這個驅動的原因。

還記得我前面舉過幾個在指令行中調用runCommand的示例嗎?如果在C#中也需要執行這樣的操作,可以調用MongoDatabase.SendCommand() 方法。比如:删除集合Category,我們可以寫成:

【MongoIdAttribute】:可以讓我們将一個C#類的資料成員映射到文檔的"_id"屬性。前面有示例說明,這裡就不再多說了。

【MongoAliasAttribute】:可以讓我們将一個C#類的資料成員在映射到文檔時采用其它的屬性名稱。 比如:我希望将CustomerName成員在儲存到MongoDB時,采用CName來儲存。

【MongoIgnoreAttribute】:可以讓一個C#類在儲存到MongoDB時,忽略某些成員。請看下面的代碼:

MongoDB不支援在查詢資料庫時使用Join操作

在MongoDB中,一個文檔就是一個完整的對象,是以擷取一個對象時,并不需要關系資料庫的那種JOIN文法。 在上面定義的OrderItem中,CustomerName并沒有儲存到資料庫,而是在加載時,采用了【引用】的設計方式, 根據CustomerID去通路集合Customer來擷取對應的CustomerName ,這也算是JOIN的常見使用場景了。

示例項目中有一個需求:根據一個日期範圍查詢訂單清單(支援分頁)。我是這樣實作這個查詢操作的。

擷取MongoDB服務端狀态

我們再來看一下當時啟動服務端的截屏吧:

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

注意最後一行,它告訴我們它有一個WEB接口,端口是 28017 ,現在我就去看看那是個什麼樣子的。

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

可以看到它提供了一些服務端的狀态資訊。 我們還可以通過通路【http://localhost:28017/_status】來獲得以JSON方式的統計資訊。

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

我們還可以通過運作用戶端的指令【db.runCommand({"serverStatus" : 1});】來擷取這些資訊:

MongoDB實戰開發 【零基礎學習,附完整Asp.net示例】

好了,就說到這裡吧。接下來,您也可以寫點代碼嘗試一下,或者下載下傳我準備的示例項目參考一下。