MongoDB学习笔记~Update方法更新集合属性后的怪问题

回到目录

在对MongoDB进行封装后,对于Update更新对象里的集合属性时出现了一个现象,让人感到很恶心,人家更新前是个美丽的Array,但是更新之后集合对象变成了键值对,键是集合的类型名称,值是真实的数组值,哈哈,这个问题起初困扰了我很久,今天终于豁然开朗了,原来是Update方法的问题,呵呵!

看原来的值

看更新后的变质的值

再看看我们的Update方法

    public Task UpdateAsync(TEntity item)
        {
            var query = new QueryDocument("_id", typeof(TEntity).GetProperty(EntityKey).GetValue(item).ToString());
            var fieldList = new List<UpdateDefinition<TEntity>>();
            foreach (var property in typeof(TEntity).GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                if (property.Name != EntityKey)//更新集中不能有实体键_id
                {
                    fieldList.Add(Builders<TEntity>.Update.Set(property.Name, property.GetValue(item)));
                }
            }

            return ForWait(() => _table.UpdateOneAsync(query, Builders<TEntity>.Update.Combine(fieldList)));

        }

确实没看出什么问题来,但最后它生成的代码是以_t和_v为键值的值,出现这种情况的原因是你的代码没有被mongo识别,就像之前我们为mongo传decimal类型的数据一样,它也会出现同样的情况。

解决方法

将复杂类型进行拆封和组装,让它被mongo所认识,这样update操作就可以按着我们预想的完成了,值得注意的是,如果你的对象里有复杂类型,如Person类里有Address类型,那么在赋值时我们拼成以下这样

Address.City="北京"

而如果你的对象里属性为集合类型,那就更麻烦一些,除了做上面的拆封外,还要关注它的索引号,如Person类里有AddList集合属性,那么在赋值时我们拼成以下这样

AddList.0.City="北京"

下面公开大叔的Update代码

        public Task UpdateAsync(TEntity item)
        {
            var query = new QueryDocument("_id", typeof(TEntity).GetProperty(EntityKey).GetValue(item).ToString());
            var fieldList = new List<UpdateDefinition<TEntity>>();
            foreach (var property in typeof(TEntity).GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                //非空的复杂类型
                if (property.PropertyType.IsClass && property.PropertyType != typeof(string) && property.GetValue(item) != null)
                {

                    if (typeof(IList).IsAssignableFrom(property.PropertyType))
                    {
                        #region 集合类型
                        foreach (var sub in property.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                        {
                            if (sub.PropertyType.IsClass && sub.PropertyType != typeof(string))
                            {
                                var arr = property.GetValue(item) as IList;
                                if (arr != null && arr.Count > 0)
                                {
                                    for (int s = 0; s < arr.Count; s++)
                                    {
                                        foreach (var subInner in sub.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                                        {
                                            //propertyName.index.innerPropertyName
                                            fieldList.Add(Builders<TEntity>.Update.Set(property.Name + "."+ s + "." + subInner.Name, subInner.GetValue(arr[s])));
                                        }
                                    }
                                }
                            }
                        }
                        #endregion
                    }
                    else
                    {
                        #region 实体类型
                        //复杂类型,导航属性,类对象和集合对象
                        foreach (var sub in property.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                        {
                            fieldList.Add(Builders<TEntity>.Update.Set(property.Name + "." + sub.Name, sub.GetValue(property.GetValue(item))));
                        }
                        #endregion
                    }
                }
                else //简单类型
                {
                    if (property.Name != EntityKey)//更新集中不能有实体键_id
                    {
                        fieldList.Add(Builders<TEntity>.Update.Set(property.Name, property.GetValue(item)));
                    }
                }
            }

            return ForWait(() => _table.UpdateOneAsync(query, Builders<TEntity>.Update.Combine(fieldList)));

        }

希望本文章对使用MongoDB的学生来说有所帮助!

回到目录

时间: 2024-10-17 09:24:33

MongoDB学习笔记~Update方法更新集合属性后的怪问题的相关文章

MongoDB学习笔记-创建、更新、删除文档

创建 MongoDB中使用insert方法来向集合插入文档,然后保存到MongoDB中. db.foo.insert({“hehe”:”呵呵”}) 如果想批量插入的话可以使用下面这种形式:db.foo.insert([{“hehe”:”呵呵”},{“haha”:”哈哈”}]) 插入校验 插入数据时MongoDB只对数据进行最基本的检查-检查文档的基本结构.如果没有“_id”字段,就会自动增加一个,所有文档都必须小于16MB(这个值是MongoDB设计者人为定义的,未来可能会增加).这样的限制主要

【MongoDB学习笔记5】MongoDB中的创建、读取、更新、删除(CRUD)

数据库会用到创建(create)读取(find)更新(update)删除(remove),MongoDB也同样会用到: 一.创建 用insert函数将文档添加到集合中.例如 创建数据库blog,将文档增加到集合post中(先将文档放入post的变量中) > post={"title":"My blog post","context":"Here's my blog post","date":new D

【MongoDB学习笔记8】深入MongoDB的更新(update)操作:修改器$set

MongoDB中文档存入数据库后用update方法更新文档,update方法有两个参数,例如 update(args1,args2) args1是指查询文档的条件: args2是指对查询到的文档进行什么样的修改: 一.文档替换 > joe1= db.post.findOne({"age":20}) {         "_id" :  ObjectId("54a530c3ff0df3732bac1680"),         "i

【MongoDB学习笔记9】深入MongoDB的更新(update)操作:修改器$inc

ongoDB中文档存入数据库后用update方法更新文档,update方法有两个参数,例如 update(args1,args2) args1是指查询文档的条件: args2是指对查询到的文档进行什么样的修改: $inc用来增加已用的键值,如果键不存在就创建: $Inc只能修改的键值必须为整数.长整型和双精度浮点型,不能是其他类型. 使用$inc增加键值: > db.post.findOne({"id":0})    {             "_id" :

MongoDB学习笔记一 ID自增长

以下是官网原文地址: http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/ 概要 MongoDB 的_id字段作为一个主键存在于所有文档的最顶层,_id必须是唯一的,而且总是具有唯一约束的索引.除了唯一约束,你可以在集合中的_id字段上使用任何值, 以下这个指南描述了在_id上创建一个自增序列的两种方式: Use Counter Collection Optimistic Loop 注意事项 一般情况

[MongoDB]学习笔记--基本操作

读取 db.collection.find() db.users.find( { age: {$gt: 18}}, {name: 1, address: 1} ).limit(5).sort({age:1}) users是collection名字,从users中查找; age是query criteria,筛选结果,代表查找name字段的值比18大的; name是projection,筛选列(1代表存在, 0代表不存在),代表返回结果中包含name,address,_id(默认包含字段)字段的值

MongoDB学习笔记系列

回到占占推荐博客索引 该来的总会来的,Ef,Redis,MVC甚至Sqlserver都有了自己的系列,MongoDB没有理由不去整理一下,这个系列都是平时在项目开发时总结出来的,希望可以为各位一些帮助和启发,文章中有对新技术的研究(Mongo驱动),对老技术的回顾(代码重构),还有对架构设计的阐述等(面向接口编程,对扩展开放,对修改关闭,所以出现了IMongoRepository接口). MongoDB学习笔记系列~目录 MongoDB学习笔记~环境搭建 (2015-03-30 10:34) M

mongodb学习笔记系列一

一.简介和安装 ./bin/mongod --dbpath /path/to/database --logpath /path/to/log --fork --port 27017 mongodb非常的占磁盘空间, 刚启动后要占3-4G左右,--smallfiles 二.基本命令 1.登录mongodb client /use/local/mongo 2.查看当前数据库 show databases; show dbs; 两个可能 3.admin是和管理有关的库,local 是放schema有关

MongoDB学习笔记(查询)

1.  基本查询:    构造查询数据.    > db.test.findOne()    {         "_id" : ObjectId("4fd58ecbb9ac507e96276f1a"),         "name" : "stephen",         "age" : 35,         "genda" : "male",