【MongoDB】递归获取字段更新表达式,更新复杂数据类型对象
在實(shí)際更新Mongo對(duì)象時(shí)發(fā)現(xiàn),原有的更新代碼無(wú)法更新復(fù)雜的數(shù)據(jù)類(lèi)型對(duì)象。恰好看到張占嶺老師有對(duì)該方法做相關(guān)的改進(jìn),因此全抄了下來(lái)。
總的核心思想就是運(yùn)用反射與遞歸,對(duì)對(duì)象屬性一層一層挖掘下去,循環(huán)創(chuàng)建父類(lèi)及之類(lèi)的更新表達(dá)式。
相關(guān)代碼如下:
#region 遞歸獲取字段更新表達(dá)式private List<UpdateDefinition<T>> GetUpdateDefinitions<T>(T entity) {var type = typeof(T);var fieldList = new List<UpdateDefinition<T>>();foreach (var property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)){GenerateRecursion<T>(fieldList, property, property.GetValue(entity), entity, "");}return fieldList; }private void GenerateRecursion<TEntity>(List<UpdateDefinition<TEntity>> fieldList,PropertyInfo property,object propertyValue,TEntity item,string father) {//復(fù)雜類(lèi)型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);elseGenerateRecursion(fieldList, subInner, subInner.GetValue(arr[index]), item, father + "." + property.Name + "." + index);}}}}}}//實(shí)體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);elseGenerateRecursion(fieldList, sub, sub.GetValue(propertyValue), item, father + "." + property.Name);}}}//簡(jiǎn)單類(lèi)型else{if (property.Name != "_id")//更新集中不能有實(shí)體鍵_id {if (string.IsNullOrWhiteSpace(father))fieldList.Add(Builders<TEntity>.Update.Set(property.Name, propertyValue));elsefieldList.Add(Builders<TEntity>.Update.Set(father + "." + property.Name, propertyValue));}} }/// <summary> /// 構(gòu)建Mongo的更新表達(dá)式 /// </summary> /// <param name="entity"></param> /// <returns></returns> private List<UpdateDefinition<T>> GeneratorMongoUpdate<T>(T item) {var fieldList = new List<UpdateDefinition<T>>();foreach (var property in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)){GenerateRecursion<T>(fieldList, property, property.GetValue(item), item, string.Empty);}return fieldList; }#endregion View Code?
在實(shí)際應(yīng)用過(guò)程中,有幾點(diǎn)要注意一下:
1.在對(duì)象創(chuàng)建時(shí),就要將對(duì)象中的數(shù)組屬性初始化,否則在更新時(shí)無(wú)法插入子項(xiàng)。
public class Users : MongoObj {public Users() {Subs = new List<Sub>();Spell = new List<int>();}public string ObjectId_id { get; set; }public string Name { get; set; }public string Sex { set; get; }public List<int> Spell { get; set; }public List<Sub> Subs { get; set; } }2.如果數(shù)組是一個(gè)復(fù)雜對(duì)象數(shù)據(jù),那么要給對(duì)象添加一個(gè)_id,并且在對(duì)象初始化時(shí)就給_id賦值。
public class Sub {public Sub() { _id = MongoDB.Bson.ObjectId.GenerateNewId().ToString();}public string _id { get; set; }public string aa {get;set;}public string bb{get;set;} }3.實(shí)際使用的時(shí)候發(fā)現(xiàn)無(wú)法對(duì)數(shù)組的子項(xiàng)做刪除。
? ?比如刪除Subs中的第一個(gè)子項(xiàng)后,再到mongo里面查詢,發(fā)現(xiàn)第一個(gè)子項(xiàng)仍然存在。
? ?暫時(shí)還沒(méi)有好的解決方法,如果有涉及到數(shù)組子項(xiàng)的刪除操作,都是將整個(gè)對(duì)象刪掉,然后再重新插入,簡(jiǎn)單粗暴。
?
轉(zhuǎn)載于:https://www.cnblogs.com/nonkicat/p/5581726.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的【MongoDB】递归获取字段更新表达式,更新复杂数据类型对象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                        - 上一篇: HDFS命令
 - 下一篇: 互联网日志的种类、存储和计算