在实际更新Mongo对象时发现,原有的更新代码无法更新复杂的数据类型对象。恰好看到张占岭老师有对该方法做相关的改进,因此全抄了下来。

总的核心思想就是运用反射递归,对对象属性一层一层挖掘下去,循环创建父类及之类的更新表达式。

相关代码如下:

#region 递归获取字段更新表达式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)
{//复杂类型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);}}}}}}//实体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);}}}//简单类型else{if (property.Name != "_id")//更新集中不能有实体键_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>
/// 构建Mongo的更新表达式
/// </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

在实际应用过程中,有几点要注意一下:

1.在对象创建时,就要将对象中的数组属性初始化,否则在更新时无法插入子项。

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.如果数组是一个复杂对象数据,那么要给对象添加一个_id,并且在对象初始化时就给_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.实际使用的时候发现无法对数组的子项做删除
   比如删除Subs中的第一个子项后,再到mongo里面查询,发现第一个子项仍然存在。

暂时还没有好的解决方法,如果有涉及到数组子项的删除操作,都是将整个对象删掉,然后再重新插入,简单粗暴。

转载于:https://www.cnblogs.com/nonkicat/p/5581726.html

【MongoDB】递归获取字段更新表达式,更新复杂数据类型对象相关推荐

  1. ONLYOFFICE文档V7.2现已发布————插件市场、实时查看器、连写、全新表单字段、UI 更新等

    ONLYOFFICE文档V7.2现已发布 ----插件市场.实时查看器.连写.全新表单字段.UI 更新等 我们已在最新版本的在线编辑器中提供了多种实用性改进,比如:轻松的插件安装流程.实时查看器.支持 ...

  2. mybatis动态查询字段、动态更新字段

    一.动态查询字段并返回list 接收的对象 @Data public class TableFieldOutput implements Serializable {private static fi ...

  3. MongoDB中的子文档批量更新

    Mongodb 3.6版本的福利好吧! 谢谢观看,转载请标注来源Thanks!©PerfumerKarma 官网文档地址: https://docs.mongodb.com/manual/refere ...

  4. SAP QM 物料主数据QM视图里字段MARC-INSMK的更新

    SAP QM 物料主数据QM视图里字段MARC-INSMK的更新 在物料主数据的质量管理视图,有一个字段'Post to Insp.stock'(MARC-INSMK)的.该字段在启用了QM模块之后, ...

  5. mysql触发器 当记录的指定字段发生变化时,更新表中的另外一个字段,或者更新另外一张关联表中关联记录的字段...

    2019独角兽企业重金招聘Python工程师标准>>> 注意:语句中出现的old,new,now(),都为数据库自带的关键字,此处不做解释. 两种情况: 第一种:一张表中,更新某条记 ...

  6. 来自网页的消息服务器繁处理忙,EventSource 对象用于接收服务器发送事件通知,是网页自动获取来自服务器的更新...

    //--------------------------------客户端代码----------------------------- if(typeof(EventSource) !== &quo ...

  7. #Oracle Clob类型字段插入与更新

    Oracle Clob类型字段插入与更新 (一)在oracle中,有一种类型叫做大对象类型,分为二进制的blob和字符型的char类型,用于存储字符串超过4000(varchar2的长度限制是4000 ...

  8. mongodb @aggregation 返回字段映射不上_MongoDB---基于分布式文件存储的数据库(二)...

    MongoDB基础入门到高级进阶视频教程 [MongoDB] 六.Document 操作 在MongoDB中文档是指多个键及其关联的值有序地放置在一起就是文档,其实指的就是数据,也是我们平时操作最多的 ...

  9. mongodb 输出数组字段_MongoDb文档操作、索引操作

    学习主题:MongoDb 学习目标: 掌握mongodb文档的更新 掌握mongodb文档的删除 掌握mongodb文档的查找 掌握mongodb文档的条件操作符 掌握mongodb中的索引操作 Mo ...

最新文章

  1. 2021年人工智能数据采集标注行业四大趋势预测
  2. while 小项目练习
  3. VS2013的项目转到VS2010需要修改的
  4. 【Flutter】Flutter 混合开发 ( 关联 Android 工程与 Flutter 工程 | 安卓页面中嵌入 Flutter 页面 | 安卓中启动 Flutter 页面 )
  5. SAP修改科目为未清项管理和行项目显示
  6. mysql merge 分区_mysql merge 分区
  7. Redhat安装tftp的方法
  8. ASP.NET Core技术研究-全面认识Web服务器Kestrel
  9. windows服务器新建管理员用户_用户和组管理
  10. 01Python可视化开发环境之Pycharm+Anaconda3安装配置详细步骤
  11. SaaS服务商盘点之ERP篇
  12. 节约里程法求解CVRP问题
  13. Linux中运行shell脚本的几种方式及其区别(source . ./myscript.sh sh myscript.sh)
  14. Frequency domain enhancement
  15. 西南大学网络作业答案计算机,2019西南大学继续教育学院《计算机基础》作业答案...
  16. 苹果电脑破音的解决办法
  17. 【CVPR2020视频超分辨率】Zooming Slow-Mo: Fast and Accurate One-Stage Space-Time Video Super-Resolution 阅读笔记
  18. 【coolshell】开源中最好的Web开发的资源
  19. 晨枫U盘维护工具的ISOLINUX模式可加载磁盘映像的探索及USB-ROM引导后安装系统的相关问题
  20. 4~20mA电流环采集电路

热门文章

  1. 如何利用python在一个wen'dang'li_如何利用Python网络爬虫给自己跟朋友来一份穷游攻略!走到哪里穷到哪里的哦!...
  2. 如何保证消息不被重复消费~~~~~(如何保证消息队列的幂等性)
  3. linux dd安装系统,通过DD命令安装Windows,并介绍几款DD镜像包
  4. 计算机基础:存储系统知识笔记(二)
  5. 手机:导致手机发烫的原因有哪些?
  6. 在程序员面前千万不要说这9句话,我一个同事就死的很惨!
  7. 程序员如何优雅度过一生的15个建议
  8. ip访问php $_files空,PHP中表单没有问题但$_FILES为空怎么办?
  9. 高考填报志愿计算机操作技巧,高考志愿填报技巧经验
  10. 克服浮躁_设计思维:您克服并赢得低迷的最终工具。