MongoDB學(xue)習筆記(ji)~大(da)叔框(kuang)架實體更新(xin)支持N層嵌(qian)套~遞(di)歸遞(di)歸我(wo)愛你!
遞(di)歸遞(di)歸我愛你!只要(yao)你想做,就(jiu)一(yi)定能成功(gong)!
從一到二,從二到三,它是容易的,也是沒什么可搞的,或者說,它是一種流水線的方式,而從三到十,從十到百,它注定要有一個質的突破,否則,它會把你累死,代碼寫的讓你自己都覺得想吐!有時,我們是被逼出來的,對于一種功能的實現,我們有時需要有從三到十的態度中,就像0的出現是人類最大的突破之一……
回(hui)歸(gui)到(dao)實例,在(zai)MongoDB中實體(ti)可(ke)以嵌(qian)套,這在(zai)C#里(li)(li)(li)叫做復雜屬(shu)性,即類中也有類級的(de)(de)(de)屬(shu)性,這在(zai)面向(xiang)(xiang)對象(xiang)里(li)(li)(li)叫做“組合”(設(she)計模(mo)式中的(de)(de)(de)組合模(mo)式),它經常在(zai)日常開發環境中見到(dao),大(da)家都耳熟能詳(xiang)了,呵呵,而(er)在(zai)mongodb里(li)(li)(li),如(ru)果(guo)希(xi)望對N層嵌(qian)套的(de)(de)(de)類型進行update操作,這絕對不是一(yi)件容易(yi)的(de)(de)(de)事(shi),最起碼在(zai)大(da)叔框架里(li)(li)(li),在(zai)面向(xiang)(xiang)linq的(de)(de)(de)語法里(li)(li)(li),它并不容易(yi),但經過大(da)叔的(de)(de)(de)努力,和對遞歸(gui)的(de)(de)(de)依賴(lai),把這個問題解決(jue)了!
這才有今天的文章:遞歸遞歸我愛你!
一 從超(chao)級(ji)變(bian)態的類開始
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> /// 聯系方式和地(di)址(zhi) /// </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; } }
看到上面的(de)(de)類,絕對(dui)夠你喝一壺(hu)的(de)(de),呵呵,這是一個(ge)復(fu)雜(za)的(de)(de)類型People,它有實體(ti)屬性(xing)contact和列表屬性(xing)OrderList
而對于之前大叔的框架里,這(zhe)種結構是不(bu)被支(zhi)持的,大叔只能(neng)支(zhi)持到(dao)3級嵌套,但(dan)這(zhe)顯然(ran)是不(bu)夠的,最后大叔硬著頭皮沖了上(shang)來,把這(zhe)個骨頭啃掉了,哈哈!
下面貢獻(xian)我的Recursion代碼
/// <summary> /// 遞歸(gui)構(gou)建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) { //復雜(za)類型 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); } } } //簡單(dan)類型 else { if (property.Name != EntityKey)//更新(xin)集(ji)中(zhong)不能(neng)有實體鍵_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的更新(xin)表達式 /// </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; }
最后(hou)的結果,當然是(shi)在N層失敗之后(hou),取得(de)了成(cheng)功,呵(he)呵(he)!
最后(hou),送給大(da)家一句,多看看數據結構和算法,對各位(wei)在程序開發領域,一定有非常大(da)的幫助,最起(qi)碼在看問題的角度上,會有更(geng)多的,更(geng)合理的選擇!