mongodb C#官方驱动2.2 update方法封装

C#官方驱动2.2的更新方式使用的是updatedefinition 的形式进行更新,因此想封装它的人太多了

写这篇文章之前,博客园确实也有不少update方法的封装,思路大概是通过反射对象属性构建来updatedefinition,如果有内部对象或者列表则继续递推构建,自己亲测发现几个问题

1. 字段decimal类型,在数据库中生成_t-_v形式保存,非常的不直观,在查询的时候直接报错——无法完成反序列化

2. string[]数组无法保存,方法有漏洞,虽然自己添加了一些判断,但是还会存在问题3

3. IList<T> 的保存问题,代码是遍历数组生成updatedefinition,但是却没有考虑到 如果数组有 3个变成2个的时候,只能更新到List[0]和List[1] 没有删除List[2]

到此我再也改不下去了,不知道还有什么坑,决定自己写一个update,思路是这样的

既然mongodb存储的是bson格式,那么可以将对象序列化为json或者bson格式进行存储,查看api发现通过bsondocument也是可以更新文档,那么假设成立,不过改需要包含legacy

的驱动,nuget对应的是mongocssharpdriver;

一开始发现api支持JSON可以转化为BsonDocument,写的是将Model进行JSON序列化,但是问题来了,它把BsonIgnore属性的字段也序列化了,从而导致查询出错,想到添加JsonIgnore属性,

程序员都知道这是万万不行的,提供api时假如有这个属性也会忽略,此法行不通

因此还得使用Bson序列化器,他可以轻松的解决BsonIgnore的问题,不管层级有多深该属性都起作用,兼容了mongodb驱动的问题而不影响其他功能。

快上班了,是上代码的时候了

 internal Task<UpdateResult> Update<T>(T entity, string[] includeFields = null, string[] excludeFields = null) where T : BaseMongoEntity
        {
            string bson = string.Empty;
            using (var sw = new StringWriter())
            {
                BsonWriter writer = new JsonWriter(sw);
                BsonSerializer.Serialize(writer, entity);
                bson = sw.GetStringBuilder().ToString();
                writer.Close();
                sw.Close();
            }
            BsonDocument bsonSetDoc = BsonSerializer.Deserialize<BsonDocument>(bson);
            //排除Id 和 _t
            bsonSetDoc.Remove("_id");
            bsonSetDoc.Remove("_t");

            //排除忽略的字段
            if (excludeFields != null && excludeFields.Length > 0)
            {
                excludeFields.Distinct().ToList().ForEach(field => { bsonSetDoc.Remove(field); });
            }
            //需要更新的字段
            if (includeFields != null && includeFields.Length > 0)
            {
                var allFields = bsonSetDoc.Select(m => m.Name).ToList();
                allFields.Except(includeFields).ToList().ForEach(field => { bsonSetDoc.Remove(field); });
            }
            var filter = new BsonDocument().AddRange(new List<BsonElement>() { new BsonElement("_id", entity.Id) });
            var update = new UpdateDocument("$set", bsonSetDoc);
            return _client.Collection<T>().UpdateOneAsync(filter, update);
        }

  当然需要注意的是,如果你仅仅是更新一两个字段或者自增字段等,还是构建updatedefinition比较合适

posted @ 2016-07-06 14:09  liusaup  阅读(581)  评论(0)    收藏  举报