最近閒的時間有點多,因此仍是寫博客吧。數據庫
有人說Mongo 2.0的寫法難以把控,好多地方不知道咋用,因此堅持用1.0(不肯意去嘗試2.0),我感受不可理解。因此寫篇博客比較下。編程
Mongo C#驅動1.0到2.0設計方面的差異很是大。c#
a.在query的構建方面,雖然有問題,可是勉強能接受異步
1 var modelCursor = collection.Find( 2 Query.And(Query.Matches("Name", "test"),Query.EQ("Age",10),Query.In("id",new BsonArray(){"123","456","sda"}))); 3 var modelCursor1 = collection.Find( 4 Query.And(Query<TestData>.Matches(t => t.Name, "test"), Query<TestData>.EQ(t=>t.Age, 10), Query<TestData>.In(t=>t._id, new BsonArray() { "123", "456", "sda" })));
第一種方式代碼簡單,可是硬字符串比較多,萬一改個字段,維護難度大異步編程
第二種方式代碼維護性好,可是代碼真是煩瑣,每一個query都要來個泛型約定,冗餘太多了優化
b.大量linq方法與數據庫中執行構建查詢的方法混在一塊兒,這點是能夠改進的。不然可能出現一下問題:this
在查詢返回類型上MongoCursor<TDefaultDocument>。繼承IEnumerable<T>,Find時只是構建查詢而已,只有調用GetEnumerator()纔回去數據庫查詢數據。也就是ToList()或者foreach的時候纔去查詢。這一點設計的沒錯跟ef一致的spa
執行方式,看看源碼截圖:.net
這樣看起來沒問題,可是在使用時,以下代碼:翻譯
這是段經常使用的分頁代碼,我天真的覺得他會將cursor.Skip().Take()生成查詢去數據庫中執行再把200條結果返回給我。可是實際狀況不是這樣的
其實已經把全部數據都拿出來了,只是在客戶端使用了linq的Skip去跳過而已。
正確的用法是:
要使用cursor的Set開頭的方法纔是構建查詢的。
若是你學ef那也學完全點啊,不信你看ef查詢時的Skip:
人家把Skip Take都「重寫」了好吧,根本沒使用IEnumerable<T>的Skip。這一點想說明的,就是致使了大量的linq客戶端執行的代碼與Mongo服務端執行的代碼混雜的問題
c.另外分組查詢是設計很是很差的。好比:
請看GroupArgs的註釋:
知道我寫這麼多註釋,爲啥嗎,我怕過兩天我也不知道咋用的了。更別說讓其餘同事用了。一個分組查詢竟然還要在c#中寫原始的js代碼來實現。因此驅動在這裏的實現只是半成品的。
a.首先查詢所有是lamda表達式了,此次算是把查詢這塊完全本地化了。不用再去記住Mongo查詢原生的語法了,門檻很低了。如:
b.重寫了查詢返回值類型,叫什麼FindFluent。翻譯過來就是可鏈式調用的東東,看看源碼:
果真都是返回的this便於鏈式調用,再看看裏面的方法:
2.0再也不繼承IEnumerable接口,裏面的方法所有是本身實現的了,好比:
findFluent.Skip(10).Limit(10).SortBy(t => t.Age);使用起來順手多了,並且都是到數據庫端執行的.
就連取集合的First方法,也是通過服務端處理的,不信你看:
你再看看Single方法:
查詢的時候都作了Limit處理,…………………………可是會不會忽然心頭一緊。怎麼Single的時候find.Limit(2)啊,太奇怪了。不過聰明的小夥伴,想一下子應該知道咋回事了,哈哈!
再看看分組查詢優化,我就不說了,把c#裏寫js代碼的部分直接搞掉了。使用lamda表達式的方式實現了,以下:
var dataGroup = collection.Aggregate().Group(t => t.Age, g => new { _id = g.Key, TotalAge = g.Sum(x => x.Age) });
須要注意的是2.0都是異步編程,熟悉下用法就好了,這也是.net4.5比較大的改變:把異步編程變得簡單。
先寫這麼多了,那裏說的不對的地方你們多多指出。另外身邊有誰還堅持用1.0的,必定要嘗試着去說服他……額……