博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于MongoDb官方C#驱动封装MongoDbCsharpHelper类(CRUD类)
阅读量:6476 次
发布时间:2019-06-23

本文共 12692 字,大约阅读时间需要 42 分钟。

近期工作中有使用到 MongoDb作为日志持久化对象,需要实现对MongoDb的增、删、改、查,但由于MongoDb的版本比较新,是2.4以上版本的,网上已有的一些MongoDb Helper类都是基于之前MongoDb旧的版本,无法适用于新版本的MongoDb,故我基于MongoDb官方C#驱动重新封装了MongoDbCsharpHelper类(CRUD类),完整代码如下:

using MongoDB;using MongoDB.Bson;using MongoDB.Driver;using System;using System.Collections;using System.Collections.Generic;using System.Linq;using System.Linq.Expressions;using System.Reflection;using System.Threading;using System.Web;namespace Zuowj.Utils{    ///     /// MongoDbCsharpHelper:MongoDb基于C#语言操作帮助类    /// Author:Zuowenjun    /// Date:2017/11/16    ///     public class MongoDbCsharpHelper    {        private readonly string connectionString = null;        private readonly string databaseName = null;        private MongoDB.Driver.IMongoDatabase database = null;        private readonly bool autoCreateDb = false;        private readonly bool autoCreateCollection = false;        static MongoDbCsharpHelper()        {            BsonDefaults.GuidRepresentation = GuidRepresentation.Standard;        }        public MongoDbCsharpHelper(string mongoConnStr, string dbName, bool autoCreateDb = false, bool autoCreateCollection = false)        {            this.connectionString = mongoConnStr;            this.databaseName = dbName;            this.autoCreateDb = autoCreateDb;            this.autoCreateCollection = autoCreateCollection;        }        #region 私有方法        private MongoClient CreateMongoClient()        {            return new MongoClient(connectionString);        }        private MongoDB.Driver.IMongoDatabase GetMongoDatabase()        {            if (database == null)            {                var client = CreateMongoClient();                if (!DatabaseExists(client, databaseName) && !autoCreateDb)                {                    throw new KeyNotFoundException("此MongoDB名称不存在:" + databaseName);                }                database = CreateMongoClient().GetDatabase(databaseName);            }            return database;        }        private bool DatabaseExists(MongoClient client, string dbName)        {            try            {                var dbNames = client.ListDatabases().ToList().Select(db => db.GetValue("name").AsString);                return dbNames.Contains(dbName);            }            catch //如果连接的账号不能枚举出所有DB会报错,则默认为true            {                return true;            }        }        private bool CollectionExists(IMongoDatabase database, string collectionName)        {            var options = new ListCollectionsOptions            {                Filter = Builders
.Filter.Eq("name", collectionName) }; return database.ListCollections(options).ToEnumerable().Any(); } private MongoDB.Driver.IMongoCollection
GetMongoCollection
(string name, MongoCollectionSettings settings = null) { var mongoDatabase = GetMongoDatabase(); if (!CollectionExists(mongoDatabase, name) && !autoCreateCollection) { throw new KeyNotFoundException("此Collection名称不存在:" + name); } return mongoDatabase.GetCollection
(name, settings); } private List
> BuildUpdateDefinition
(object doc, string parent) { var updateList = new List
>(); foreach (var property in typeof(TDoc).GetProperties(BindingFlags.Instance | BindingFlags.Public)) { var key = parent == null ? property.Name : string.Format("{0}.{1}", parent, property.Name); //非空的复杂类型 if ((property.PropertyType.IsClass || property.PropertyType.IsInterface) && property.PropertyType != typeof(string) && property.GetValue(doc) != null) { if (typeof(IList).IsAssignableFrom(property.PropertyType)) { #region 集合类型 int i = 0; var subObj = property.GetValue(doc); foreach (var item in subObj as IList) { if (item.GetType().IsClass || item.GetType().IsInterface) { updateList.AddRange(BuildUpdateDefinition
(doc, string.Format("{0}.{1}", key, i))); } else { updateList.Add(Builders
.Update.Set(string.Format("{0}.{1}", key, i), item)); } i++; } #endregion } else { #region 实体类型 //复杂类型,导航属性,类对象和集合对象 var subObj = property.GetValue(doc); foreach (var sub in property.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { updateList.Add(Builders
.Update.Set(string.Format("{0}.{1}", key, sub.Name), sub.GetValue(subObj))); } #endregion } } else //简单类型 { updateList.Add(Builders
.Update.Set(key, property.GetValue(doc))); } } return updateList; } private void CreateIndex
(IMongoCollection
col, string[] indexFields, CreateIndexOptions options = null) { if (indexFields == null) { return; } var indexKeys = Builders
.IndexKeys; IndexKeysDefinition
keys = null; if (indexFields.Length > 0) { keys = indexKeys.Descending(indexFields[0]); } for (var i = 1; i < indexFields.Length; i++) { var strIndex = indexFields[i]; keys = keys.Descending(strIndex); } if (keys != null) { col.Indexes.CreateOne(keys, options); } } #endregion public void CreateCollectionIndex
(string collectionName, string[] indexFields, CreateIndexOptions options = null) { CreateIndex(GetMongoCollection
(collectionName), indexFields, options); } public void CreateCollection
(string[] indexFields = null, CreateIndexOptions options = null) { string collectionName = typeof(TDoc).Name; CreateCollection
(collectionName, indexFields, options); } public void CreateCollection
(string collectionName, string[] indexFields = null, CreateIndexOptions options = null) { var mongoDatabase = GetMongoDatabase(); mongoDatabase.CreateCollection(collectionName); CreateIndex(GetMongoCollection
(collectionName), indexFields, options); } public List
Find
(Expression
> filter, FindOptions options = null) { string collectionName = typeof(TDoc).Name; return Find
(collectionName, filter, options); } public List
Find
(string collectionName, Expression
> filter, FindOptions options = null) { var colleciton = GetMongoCollection
(collectionName); return colleciton.Find(filter, options).ToList(); } public List
FindByPage
(Expression
> filter, Expression
> keySelector, int pageIndex, int pageSize, out int rsCount) { string collectionName = typeof(TDoc).Name; return FindByPage
(collectionName, filter, keySelector, pageIndex, pageSize, out rsCount); } public List
FindByPage
(string collectionName, Expression
> filter, Expression
> keySelector, int pageIndex, int pageSize, out int rsCount) { var colleciton = GetMongoCollection
(collectionName); rsCount = colleciton.AsQueryable().Where(filter).Count(); int pageCount = rsCount / pageSize + ((rsCount % pageSize) > 0 ? 1 : 0); if (pageIndex > pageCount) pageIndex = pageCount; if (pageIndex <= 0) pageIndex = 1; return colleciton.AsQueryable(new AggregateOptions { AllowDiskUse = true }).Where(filter).OrderByDescending(keySelector).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); } public void Insert
(TDoc doc, InsertOneOptions options = null) { string collectionName = typeof(TDoc).Name; Insert
(collectionName, doc, options); } public void Insert
(string collectionName, TDoc doc, InsertOneOptions options = null) { var colleciton = GetMongoCollection
(collectionName); colleciton.InsertOne(doc, options); } public void InsertMany
(IEnumerable
docs, InsertManyOptions options = null) { string collectionName = typeof(TDoc).Name; InsertMany
(collectionName, docs, options); } public void InsertMany
(string collectionName, IEnumerable
docs, InsertManyOptions options = null) { var colleciton = GetMongoCollection
(collectionName); colleciton.InsertMany(docs, options); } public void Update
(TDoc doc, Expression
> filter, UpdateOptions options = null) { string collectionName = typeof(TDoc).Name; var colleciton = GetMongoCollection
(collectionName); List
> updateList = BuildUpdateDefinition
(doc, null); colleciton.UpdateOne(filter, Builders
.Update.Combine(updateList), options); } public void Update
(string collectionName, TDoc doc, Expression
> filter, UpdateOptions options = null) { var colleciton = GetMongoCollection
(collectionName); List
> updateList = BuildUpdateDefinition
(doc, null); colleciton.UpdateOne(filter, Builders
.Update.Combine(updateList), options); } public void Update
(TDoc doc, Expression
> filter, UpdateDefinition
updateFields, UpdateOptions options = null) { string collectionName = typeof(TDoc).Name; Update
(collectionName, doc, filter, updateFields, options); } public void Update
(string collectionName, TDoc doc, Expression
> filter, UpdateDefinition
updateFields, UpdateOptions options = null) { var colleciton = GetMongoCollection
(collectionName); colleciton.UpdateOne(filter, updateFields, options); } public void UpdateMany
(TDoc doc, Expression
> filter, UpdateOptions options = null) { string collectionName = typeof(TDoc).Name; UpdateMany
(collectionName, doc, filter, options); } public void UpdateMany
(string collectionName, TDoc doc, Expression
> filter, UpdateOptions options = null) { var colleciton = GetMongoCollection
(collectionName); List
> updateList = BuildUpdateDefinition
(doc, null); colleciton.UpdateMany(filter, Builders
.Update.Combine(updateList), options); } public void Delete
(Expression
> filter, DeleteOptions options = null) { string collectionName = typeof(TDoc).Name; Delete
(collectionName, filter, options); } public void Delete
(string collectionName, Expression
> filter, DeleteOptions options = null) { var colleciton = GetMongoCollection
(collectionName); colleciton.DeleteOne(filter, options); } public void DeleteMany
(Expression
> filter, DeleteOptions options = null) { string collectionName = typeof(TDoc).Name; DeleteMany
(collectionName, filter, options); } public void DeleteMany
(string collectionName, Expression
> filter, DeleteOptions options = null) { var colleciton = GetMongoCollection
(collectionName); colleciton.DeleteMany(filter, options); } public void ClearCollection
(string collectionName) { var colleciton = GetMongoCollection
(collectionName); var inddexs = colleciton.Indexes.List(); List
> docIndexs = new List
>(); while (inddexs.MoveNext()) { docIndexs.Add(inddexs.Current); } var mongoDatabase = GetMongoDatabase(); mongoDatabase.DropCollection(collectionName); if (!CollectionExists(mongoDatabase, collectionName)) { CreateCollection
(collectionName); } if (docIndexs.Count > 0) { colleciton = mongoDatabase.GetCollection
(collectionName); foreach (var index in docIndexs) { foreach (IndexKeysDefinition
indexItem in index) { try { colleciton.Indexes.CreateOne(indexItem); } catch { } } } } } }}

对上述代码中几个特别的点进行简要说明:

1.由于MongoClient.GetDatabase 获取DB、MongoClient.GetCollection<TDoc> 获取文档(也可称为表)的方法 都有一个特点,即:如果指定的DB名称、Collection名称不存在,则会直接创建,但有的时候可能是因为DB名称、Collection名称写错了导致误创建了的DB或Collection,那就引起不必要的麻烦,故在MongoDbCsharpHelper类类内部封装了两个私有的方法:DatabaseExists(判断DB是否存在,如是连接的账号没有检索DB的权限可能会报错,故代码中加了直接返回true)、CollectionExists(判断Collection是否存在);

2.每个CRUD方法,我都分别重载了两个方法,一个是无需指定Collection名称,一个是需要指定Collection名称,为什么这么做呢?原因很简单,因为有时Collection的结构是相同的但又是不同的Collection,这时TDoc是同一个实体类,但collectionName却是不同的;

3.分页查询的时候如果Collection的数据量比较大,那么就会报类似错误:exception: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation. Pass allowDiskUse:true,根据报错提示,我们在查询大数据量时增加AggregateOptions对象,如: colleciton.AsQueryable(new AggregateOptions { AllowDiskUse = true })

4.ClearCollection清除Collection的所有数据,如果Collection的数据量非常大,那么直接使用colleciton.DeleteMany可能需要很久,有没有类似SQL SERVER 的truncate table的方法呢?经过多方论证,很遗憾并没有找到同类功能的方法,只有DropCollection方法,而这个DropCollection方法是直接删除Collection,当然包括Collection的所有数据,效率也非常高,但是由于是Drop,Collection就不存在了,如果再访问有可能会报Collection不存在的错误,那有没有好的办法解决了,当然有,那就是先DropCollection 然后再CreateCollection,最后别忘了把原有的索引插入到新创建的Collection中,这样就实现了truncate 初始化表的作用,当然在创建索引的时候,有的时候可能报报错(如:_id),因为_id默认就会被创建索引,再创建可能就会报错,故colleciton.Indexes.CreateOne外我加了try catch,如果报错则忽略。

5.CreateCollection(创建集合)、CreateCollectionIndex(创建集合索引)因为有的时候我们需要明确的去创建一个Collection或对已有的Collection创建索引,如果通过shell命令会非常不方便,故在此封装了一下。

 使用示例如下:

var mongoDbHelper = new MongoDbCsharpHelper("MongoDbConnectionString", "LogDB");            mongoDbHelper.CreateCollection
("SysLog1",new[]{"LogDT"}); mongoDbHelper.Find
("SysLog1", t => t.Level == "Info"); int rsCount=0; mongoDbHelper.FindByPage
("SysLog1",t=>t.Level=="Info",t=>t,1,20,out rsCount); mongoDbHelper.Insert
("SysLog1",new SysLogInfo { LogDT = DateTime.Now, Level = "Info", Msg = "测试消息" }); mongoDbHelper.Update
("SysLog1",new SysLogInfo { LogDT = DateTime.Now, Level = "Error", Msg = "测试消息2" },t => t.LogDT==new DateTime(1900,1,1)); mongoDbHelper.Delete
(t => t.Level == "Info"); mongoDbHelper.ClearCollection
("SysLog1");

 

转载地址:http://hhlko.baihongyu.com/

你可能感兴趣的文章
BZOJ5020 [THUWC 2017]在美妙的数学王国中畅游LCT
查看>>
hdu 6030 矩阵快速幂
查看>>
tomcat类加载机制
查看>>
ado.net2.0中的缓存使用SqlDependency类
查看>>
Java基础学习总结(94)——Java线程再学习
查看>>
iOS开发之调用系统设置
查看>>
利用 ACPI\\ACPI0003设备 判断笔记本还是台式机
查看>>
解决wampserver 服务无法启动
查看>>
ES6中Promise封装ajax的写法
查看>>
初次使用 VUX
查看>>
javascript 字符串转数字的简便写法
查看>>
html之div始终停留在屏幕中间部分
查看>>
Spring中jdbcTemplate的用户实例
查看>>
[模板] 快速傅里叶变换/FFT/NTT
查看>>
DecimalFormat 数据格式设置 SimpleDateFormat时间格式的用法介绍 --转载
查看>>
Android 的Margin和Padding属性以及支持的长度单位
查看>>
HDU ACM 1050 Moving Tables
查看>>
Django templates加载css/js/image等静态资源
查看>>
Eclipse C + GTK2.0环境构筑
查看>>
caffe solver
查看>>