1. 程式人生 > >MongoDB學習筆記~大叔框架實體更新支援N層巢狀~遞迴遞迴我愛你!

MongoDB學習筆記~大叔框架實體更新支援N層巢狀~遞迴遞迴我愛你!

回到目錄

遞迴遞迴我愛你!只要你想做,就一定能成功!

從一到二,從二到三,它是容易的,也是沒什麼可搞的,或者說,它是一種流水線的方式,而從三到十,從十到百,它註定要有一個質的突破,否則,它會把你累死,程式碼寫的讓你自己都覺得想吐!有時,我們是被逼出來的,對於一種功能的實現,我們有時需要有從三到十的態度中,就像0的出現是人類最大的突破之一……

迴歸到例項,在MongoDB中實體可以巢狀,這在C#裡叫做複雜屬性,即類中也有類級的屬性,這在面向物件裡叫做“組合”(設計模式中的組合模式),它經常在日常開發環境中見到,大家都耳熟能詳了,呵呵,而在mongodb裡,如果希望對N層巢狀的型別進行update操作,這絕對不是一件容易的事,最起碼在大叔框架裡,在面向linq的語法裡,它並不容易,但經過大叔的努力,和對遞迴的依賴,把這個問題解決了!

這才有今天的文章:遞迴遞迴我愛你!

一 從超級變態的類開始

 public class Person : Base
    {

        public Person()
        {
            Contact = new Test.Contact();
            OrderList = new List<Order>();
        }


        public string Name { get; set; }
        public DateTime LastContact { get
; set; } public DateTime Birthday { get; set; } public int Age { get; set; } #region 值物件 /// <summary> /// 統計 /// </summary> public Total Total { get; set; } /// <summary> /// 聯絡方式和地址 /// </summary> public
Contact Contact { get; set; } #endregion #region 列表實體 public List<Order> OrderList { get; set; } #endregion } public class Section { public string SectionID { get; set; } public string SectionName { get; set; } } public class Area { public Area() { Section = new Section(); } public string Province { get; set; } public string City { get; set; } public string District { get; set; } public Section Section { get; set; } } public class Contact { public Contact() { Area = new Area(); } public string PostCode { get; set; } public string Email { get; set; } public string Phone { get; set; } public Area Area { get; set; } } public class Total { public int Count { get; set; } public int Max { get; set; } } public class Order { public Order() { Id = MongoDB.Bson.ObjectId.GenerateNewId().ToString(); this.OrderDetail = new List<OrderDetail>(); this.User_Info = new User_Info(); } public string UserId { get; set; } public string UserName { get; set; } public string Id { get; set; } public double Price { get; set; } public DateTime AddTime { get; set; } public User_Info User_Info { get; set; } public List<OrderDetail> OrderDetail { get; set; } } public class User_Info { public User_Info() { Id = MongoDB.Bson.ObjectId.GenerateNewId().ToString(); } public string Id { get; set; } public string Name { get; set; } } public class OrderDetail { public OrderDetail() { Id = MongoDB.Bson.ObjectId.GenerateNewId().ToString(); } public string Id { get; set; } public string OrderId { get; set; } public string ProductName { get; set; } public int Count { get; set; } public double Price { get; set; } public string SellerId { get; set; } }

看到上面的類,絕對夠你喝一壺的,呵呵,這是一個複雜的型別People,它有實體屬性contact和列表屬性OrderList

而對於之前大叔的框架裡,這種結構是不被支援的,大叔只能支援到3級巢狀,但這顯然是不夠的,最後大叔硬著頭皮衝了上來,把這個骨頭啃掉了,哈哈!

下面貢獻我的Recursion程式碼

        /// <summary>
        /// 遞迴構建Update操作串
        /// </summary>
        /// <param name="fieldList"></param>
        /// <param name="property"></param>
        /// <param name="propertyValue"></param>
        /// <param name="item"></param>
        /// <param name="father"></param>
        private void GenerateRecursion(
              List<UpdateDefinition<TEntity>> fieldList,
              PropertyInfo property,
              object propertyValue,
              TEntity item,
              string father)
        {
            //複雜型別
            if (property.PropertyType.IsClass && property.PropertyType != typeof(string) && propertyValue != null)
            {
                //集合
                if (typeof(IList).IsAssignableFrom(propertyValue.GetType()))
                {
                    foreach (var sub in property.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                    {
                        if (sub.PropertyType.IsClass && sub.PropertyType != typeof(string))
                        {
                            var arr = propertyValue as IList;
                            if (arr != null && arr.Count > 0)
                            {
                                for (int index = 0; index < arr.Count; index++)
                                {
                                    foreach (var subInner in sub.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                                    {
                                        if (string.IsNullOrWhiteSpace(father))
                                            GenerateRecursion(fieldList, subInner, subInner.GetValue(arr[index]), item, property.Name + "." + index);
                                        else
                                            GenerateRecursion(fieldList, subInner, subInner.GetValue(arr[index]), item, father + "." + property.Name + "." + index);
                                    }
                                }
                            }
                        }
                    }
                }
                //實體
                else
                {
                    foreach (var sub in property.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                    {

                        if (string.IsNullOrWhiteSpace(father))
                            GenerateRecursion(fieldList, sub, sub.GetValue(propertyValue), item, property.Name);
                        else
                            GenerateRecursion(fieldList, sub, sub.GetValue(propertyValue), item, father + "." + property.Name);
                    }
                }
            }
            //簡單型別
            else
            {
                if (property.Name != EntityKey)//更新集中不能有實體鍵_id
                {
                    if (string.IsNullOrWhiteSpace(father))
                        fieldList.Add(Builders<TEntity>.Update.Set(property.Name, propertyValue));
                    else
                        fieldList.Add(Builders<TEntity>.Update.Set(father + "." + property.Name, propertyValue));
                }
            }
        }

        /// <summary>
        /// 構建Mongo的更新表示式
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        private List<UpdateDefinition<TEntity>> GeneratorMongoUpdate(TEntity item)
        {
            var fieldList = new List<UpdateDefinition<TEntity>>();
            foreach (var property in typeof(TEntity).GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                GenerateRecursion(fieldList, property, property.GetValue(item), item, string.Empty);
            }
            return fieldList;
        }

最後的結果,當然是在N層失敗之後,取得了成功,呵呵!

相關推薦

MongoDB學習筆記~大叔框架實體更新支援N~

回到目錄 遞迴遞迴我愛你!只要你想做,就一定能成功! 從一到二,從二到三,它是容易的,也是沒什麼可搞的,或者說,它是一種流水線的方式,而從三到十,從十到百,它註定要有一個質的突破,否則,它會把你累死,程式碼寫的讓你自己都覺得想吐!有時,我們是被逼出來的,對於一種功能的實現,我們有時需要有從三到十的態度中,

MongoDB學習筆記~大叔分享批量新增—批量更新—批量刪除

回到目錄 說它是批量操作,就是說將集合物件一次提交到伺服器,並對資料進行持久化,如果您的程式碼是一次一次的提交,那不算是批量操作!在之前的mongodb倉儲中並沒有對批量更新和批量刪除進行實現,而今天在專案中,還是實現了這種批量的操作,並且已經通過測試,下面公開一下原始碼 public

MongoDB學習筆記~為IMongoRepository介面更新指定欄位

回到目錄 對於MongoDB來說,它的更新建議是對指定欄位來說的,即不是把物件裡的所有欄位都進行update,而是按需去更新,這在效能上是最優的,這當然也是非常容易理解的,我們今天要實現的就是這種按需去更新,並且,我還是不希望將MongoDB的核心暴露出去,這時,我想到了EF時候的按需要更新,即為實體哪些屬

React 學習筆記 (七)(路由及路由 react-router 4.x 基本配置及使用)

react-router 路由 根據使用者訪問的地址動態的載入不同的元件 1.安裝 npm install react-router-dom --save 2.引入 import { BrowserRouter as Router, Route, Link } fr

VUE學習筆記(三)-子路由、多路由、路由、動態路由都是什麼鬼?

最近學習到VUE路由這塊,發現這塊知識點有點多,好容易混亂,我的學習習慣就是先要建立框架,然後再去挨個學習搞懂,所以先來把概念搞搞清楚再說。 首先,我們要知道VUE路由建立的是單頁面路由。 子路由其實和單路由意思是一樣的,單路由應該很好理解,因為我們都知道路由是可以一層一層巢狀的,你可以

MongoDB學習筆記~MongoDB實體中的值物件

回到目錄 注意,這裡說的值物件是指在MongoDB實體類中的,並不是DDD中的值物件,不過,兩者也是聯絡,就是它是對類的補充,自己本身沒有存在的價值,而在值物件中,也是不需要有主鍵Id的,這與DDD也是不謀而合的,也是可以理解的,因為它只是對主物件的一種補充說明,自己不存在任何意義,所以要主鍵也沒什麼用,呵

MongoDB學習筆記~官方驅動陣列物件的更新

回到目錄 對於陣列物件mongodb本身是支援的,不過對於陣列的更新,mongodb的Csharp驅動目前只支援一級,即你的物件裡包含陣列,而陣列又包括陣列,這表示兩層,這在更新子陣列時,Csharp驅動是不支援的,今天要說的就是如何讓它支援子陣列的更新,下面是我給出的資料結構 在Mongodb的Cs

MongoDB學習筆記~自己封裝的Curd操作(按需更新的先決條件)

回到目錄 我們上一講中介紹了大叔封裝的Mongo倉儲,其中介紹了幾個不錯的curd操作,而對於按需更新內部子物件,它是有條件的,即你的子物件不能為null,也就是說,我們在建立主物件時,應該為子物件賦一下初值,即new一下它,呵呵. 正確的mongo集合 對於賦過初值的子物件,在按需要更新時,有以下

MongoDB學習筆記~地圖座標的支援與附近點的查詢

回到目錄 Mongodb這個資料庫很不錯,它的方法也不錯,為了實現座標功能,它甚至為我們提供了geo裡的一些演算法,幫助我們通過某個點去位置和查詢N個附近的點。 表面 在您儲存地理資料和編寫查詢條件前,首先,您必須選擇表面型別,這將被用在計算中。您所選擇的型別將會影響您的資料如何被儲存,建立的索引的型別

MongoDB學習筆記~自己封裝的Curd操作(查詢集合物件屬性,更新集合物件)

回到目錄 我不得不說,mongodb官方驅動在與.net結合上做的不是很好,不是很理想,所以,我決定對它進行了二次封裝,這是顯得很必然了,每個人都希望使用簡單的物件,而對使用複雜,麻煩,容易出錯的物件盡而遠之,這是正常的,人都是喜歡懶惰的,就像程式設計師,也是一樣,喜歡偷懶,可能說,偷懶是程式設計師進步的一

MongoDB學習筆記~資料結構與實體物件不一致時,它會怎麼樣?

回到目錄 對於MongoDB這個文件型弱型別資料庫,它在操作時有時給我們帶來了一些方便,如當你的mongodb資料表與現有的類實體物件不一致時,會發生一些情況,總結如下 1:mongodb資料表不存在,實體類有,進行獲取資料時,程式不出錯 2:mongodb資料表沒有某些屬性欄位,實體類有,進行獲取

MongoDB學習筆記~Update方法更新集合屬性後的怪問題

回到目錄 在對MongoDB進行封裝後,對於Update更新物件裡的集合屬性時出現了一個現象,讓人感到很噁心,人家更新前是個美麗的Array,但是更新之後集合物件變成了鍵值對,鍵是集合的型別名稱,值是真實的陣列值,哈哈,這個問題起初困擾了我很久,今天終於豁然開朗了,原來是Update方法的問題,呵呵! 看

MongoDB學習筆記~使用原生語句實現三集合關係的更新

回到目錄 MongoDB的文件型資料結構使得它在儲存資料上很像JSON,在可讀性方面很強,然而這種複雜的結構在update時相對麻煩一些,而對於官方給出的文件說的也不夠細緻,有些東西也是模稜兩可的態度,對於多層巢狀的集合物件,實現update更是麻煩,而目前我們所驗證的是,原生語句最多支援三層集合物件,層次

MongoDB學習筆記 MongoDB的插入更新--upsert

轉自:http://www.guoxk.com/node/483 我們在使用MongoDB的update時,如果設定第三個引數為true,會在沒有找到文件的情況下新建一個文件,下面是一個例子 >db.foo.find(){ "_id" : ObjectId("4e9

mongoDB學習筆記(一)

介紹 tle 狀態 負載 tutorial dir 基於 管理 集合 說明: MongoDB由databases組成,database由collections組成,collection由documents組成,document由fileds組成。MongoDB是異步寫數據

MongoDB學習筆記(二)

.get 條件過濾 條件 $set system.in ins version tle 不存在 一、Mongodb命令 說明:Mongodb命令是區分大小寫的,使用的命名規則是駝峰命名法。 對於database和collection無需主動創建,在插入數據時,如果dat

MongoDB學習筆記—常用命令

upd 鍵值 操作 false doc cer 查看 數據庫 創建 這裏記錄一下MongoDB常用的命令 數據庫相關 創建數據庫 use DATABASE_NAME 如果數據庫不存在,則創建數據庫,否則切換到指定數據庫。 刪除數據庫:切換到要刪除的數據庫下,執行

MongoDB 學習筆記之 權限管理基礎

顯示 命令 修改 技術 sky 需要 bad 官方 改密碼 權限管理基礎 MongoDB有很多用戶roles,這裏只是簡單列舉下命令的使用,具體的role的含義,請查閱官方文檔。 https://docs.mongodb.com/manual/reference/bui

MongoDB 學習筆記之 分片和副本集混合運用

comment ssm table mmap insert ise class 學習 urn 分片和副本集混合運用: 基本架構圖: 搭建詳細配置: 3個shard + 3個replicat set + 3個configserver + 3個Mongos sh

MongoDB 學習筆記之 手動預先分片

var http strong str 可見 mongod 手動 ++ 1-1 手動預先分片: 目的:手動預先分片是為了防止未來chunk的移動,減少IO。 sh.shardCollection("shop.users",{"userId": 1 }) for(v