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

在实际更新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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/287350.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java openxml 操作 word,openxml word转成xml

word2007无法打开Office Open XML 文档由于种种原因&#xff0c;如程序安装错误、注册表被修改&#xff0c;或系统被病毒侵害等。有时候会造成WORD 2007无法打开.DOC文档的问题&#xff0c;常规的处理办法(右键选择“打开方式”)无效。可以试试如下的方法 &#xff1a;1.打开注…

聊一聊CLR源码中的 #define 是怎么玩的

一&#xff1a;背景 如果大家看过 CLR 源码&#xff0c;会发现里面有很多 #define 宏定义,比如说 fusionhelpers.hpp 头文件里。如果你不熟悉 C &#xff0c;看到这些 #define 应该会很晕的&#xff0c;这篇我们就来简单聊聊 define 的玩法&#xff0c;其实说白了很简单, #defi…

《看聊天记录都学不会C语言?太菜了吧》(11)2分钟领悟数组

若是大一学子或者是真心想学习刚入门的小伙伴可以私聊我&#xff0c;若你是真心学习可以送你书籍&#xff0c;指导你学习&#xff0c;给予你目标方向的学习路线&#xff0c;无套路&#xff0c;博客为证。 本系列文章将会以通俗易懂的对话方式进行教学&#xff0c;对话中将涵盖…

基于CentOS 7配置Nginx正向代理

Nginx是一款以轻量级、低内存开销、支持缓存、支持反向代理&#xff0c;负载均衡&#xff0c;电子邮件服务而著称。对于鲜为人知的是&#xff0c;它还可以作为一个简单易用的正向代理服务器。本文简要描述这个正向代理功能并给出演示&#xff0c;供大家参考。 有关Nginx的安装请…

【ArcObject开发】实验:ArcObject地图开发基本操作

ArcObjects,是基于Microsoft COM技术所构建的一系列COM组件集,是在ArcGIS Desktop平台基础上的二次开发,开发语言为VBA(Vistal Basic for Application)。下面将AO开发的中的一系统基本操作做一简单的说明。 下图是功能主面板,有三个主要功能:地图漫游、地图制图和创建元素…

[Python MoviePy 音视频开发零基础到实战] 一、用6条代码为你的视频裁剪以及添加水印

一、MoviePy 安装及配置 在 Python 有一个音视频开发模块 MoviePy&#xff0c;MoviePy 依赖于 FFmepg&#xff0c;使用 MoviePy 可以对音视频进行编辑&#xff1b;例如视频合成、视频处理、视频特效等。 在 Python 下直接使用 pip 工具进行安装即可&#xff1a; pip install…

C# 使用ILogger接口编写日志

.NET 有几种不同的日志记录和跟踪工具&#xff0c;还有许多不同的第三方日志记录程序。尝试将一个应用程序从一种日志记录技术更改为另一种日志记录技术不是一件容易的事情&#xff0c;因为日志记录 API 的使用分布在整个源代码中。要使日志记录独立于任何日志记录技术&#xf…

html页面调用php常量,js中的常量变量以及html文档三种引入js的方式

js 是基于事件驱动的异步单线程的脚本编程语言&#xff0c;它的全称是 JavaScript&#xff0c;虽然里边有个 java 字样&#xff0c;但是和 java 编程语言一点关系都没有。它是一种脚本语言&#xff0c;基于解释器执行&#xff0c;它是边解释便执行的语言。浏览器控制台 Console…

【ArcGIS风暴】基于ArcGIS空间分析功能研究渭河流域镇驻地空间分布格局

【内容提要】:基于ArcGIS平台,借助空间分析的方法,用空间平滑法(基于移动搜索法FAC和核估计)分析渭河流域镇驻地的分布特征。 实验过程 1. 加载数据 渭河流域的居民点(Resident_point.shp),DEM(等高线)、水系(线)、道路(线)空间数据,如下图所示。

基于iSroll 5.0实现的上拉加载和下拉刷新插件

Updownload.js 基于iSroll 5.0实现的上拉加载和下拉刷新插件 移动端效果比较好&#xff0c;开发者工具打开后&#xff0c;需要刷新下页面。 [演示地址:] https://chenyk2016.github.io/upDownLoad/demo.html [github地址:] https://github.com/chenyk2016/upDownLoad/ 效果图 1…

[小白进] 大佬们学习为什么简单?小白该如何学习?学历不高如何找工作?副业很好赚?了解后少走弯路

一、前言 对于新手来说&#xff0c;最开始学习编程的难度不亚于学天书&#xff0c;那为什么有经验的程序员在接触一门新技术时能够快速的上手并且完成一些需求的开发呢&#xff1f; 有些人可能看了这个问题觉得我在说废话&#xff0c;“有经验那不快那怎么才快&#xff1f;”…

Chrome如何离线安装crx文件

2019独角兽企业重金招聘Python工程师标准>>> 在Chrome浏览器的谷歌网上应用商店Chrome Web Store上点击应用安装按钮「添加至Chrome」&#xff0c;变成下载文件。把下载文件一拖进浏览器也不能安装。下面是如何离线安装crx文件的方法&#xff1a; ①点击Google Chr…

基于.NetCore开发博客项目 StarBlog - (6) 页面开发之博客文章列表

系列文章基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客&#xff1f;基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目基于.NetCore开发博客项目 StarBlog - (3) 模型设计基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入基于.N…

《看聊天记录都学不会C语言?太菜了吧》(12)循环有多容易?你看一眼就怀...

若是大一学子或者是真心想学习刚入门的小伙伴可以私聊我&#xff0c;若你是真心学习可以送你书籍&#xff0c;指导你学习&#xff0c;给予你目标方向的学习路线&#xff0c;无套路&#xff0c;博客为证。 本系列文章将会以通俗易懂的对话方式进行教学&#xff0c;对话中将涵盖…

***ECharts图表入门和最佳实践

ECharts数据图表系统&#xff1f; 5分钟上手&#xff01; 【ECharts简介】 ECharts开源来自百度商业前端数据可视化团队&#xff0c;基于html5 Canvas&#xff0c;是一个纯Javascript图表库&#xff0c;提供直观&#xff0c;生动&#xff0c;可交互&#xff0c;可个性化定制的数…

WPF|一个比较简单带点设计的登录界面

阅读目录效果展示准备简单说明 源码结尾&#xff08;视频及源码仓库&#xff09;1. 效果展示欣赏效果&#xff1a;2. 准备创建一个WPF工程&#xff0c;比如站长使用 .NET 7[1] 创建名为 Login5 的WPF项目。找一张图片做为装饰&#xff0c;放登录表单左侧&#xff1a;添加Nuget…

Android插件基础之类加载器学习

记录学习java 加载器学习所获心得&#xff0c;逐步记录了解java加载器的过程。为了知悉android 插件化的实现原理&#xff0c;从而需要从头了解android加载apk&#xff0c;以及基础的java类加载的加载过程情况&#xff0c;为方便记录和记忆&#xff0c;故此将学习了解的过程记录…

《看聊天记录都学不会C语言?太菜了吧》(13)(9*9 乘法表)寻找电脑中的盲盒彩蛋

若是大一学子或者是真心想学习刚入门的小伙伴可以私聊我&#xff0c;若你是真心学习可以送你书籍&#xff0c;指导你学习&#xff0c;给予你目标方向的学习路线&#xff0c;无套路&#xff0c;博客为证。 本系列文章将会以通俗易懂的对话方式进行教学&#xff0c;对话中将涵盖…

Fragment使用--文章集锦

android使用Fragment实现底部菜单使用show()和hide()来切换以保持Fragment状态Android Fragment 真正的完全解析&#xff08;上&#xff09;Android Fragment实践(一)纠正对Fragment Transaction BackStack的误解多个Fragment 切换时不重新实例化Fragment详解之四——管理Fragm…

使用 Postman 实现 API 自动化测试

1背景介绍 相信大部分开发人员和测试人员对 postman 都十分熟悉&#xff0c;对于开发人员和测试人员而言&#xff0c;使用 postman 来编写和保存测试用例会是一种比较方便和熟悉的方式。但 postman 本身是一个图形化软件&#xff0c;相对较难或较麻烦&#xff08;如使用 …