基于MongoDb官方C#驱动封装MongoDbCsharpHelper类(CRUD类)
近期工作中有使用到 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
- {
- /// <summary>
- /// MongoDbCsharpHelper:MongoDb基于C#语言操作帮助类
- /// Author:Zuowenjun
- /// Date:2017/11/16
- /// </summary>
- 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<BsonDocument>.Filter.Eq("name", collectionName)
- };
- return database.ListCollections(options).ToEnumerable().Any();
- }
- private MongoDB.Driver.IMongoCollection<TDoc> GetMongoCollection<TDoc>(string name, MongoCollectionSettings settings = null)
- {
- var mongoDatabase = GetMongoDatabase();
- if (!CollectionExists(mongoDatabase, name) && !autoCreateCollection)
- {
- throw new KeyNotFoundException("此Collection名称不存在:" + name);
- }
- return mongoDatabase.GetCollection<TDoc>(name, settings);
- }
- private List<UpdateDefinition<TDoc>> BuildUpdateDefinition<TDoc>(object doc, string parent)
- {
- var updateList = new List<UpdateDefinition<TDoc>>();
- 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<TDoc>(doc, string.Format("{0}.{1}", key, i)));
- }
- else
- {
- updateList.Add(Builders<TDoc>.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<TDoc>.Update.Set(string.Format("{0}.{1}", key, sub.Name), sub.GetValue(subObj)));
- }
- #endregion
- }
- }
- else //简单类型
- {
- updateList.Add(Builders<TDoc>.Update.Set(key, property.GetValue(doc)));
- }
- }
- return updateList;
- }
- private void CreateIndex<TDoc>(IMongoCollection<TDoc> col, string[] indexFields, CreateIndexOptions options = null)
- {
- if (indexFields == null)
- {
- return;
- }
- var indexKeys = Builders<TDoc>.IndexKeys;
- IndexKeysDefinition<TDoc> 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<TDoc>(string collectionName, string[] indexFields, CreateIndexOptions options = null)
- {
- CreateIndex(GetMongoCollection<TDoc>(collectionName), indexFields, options);
- }
- public void CreateCollection<TDoc>(string[] indexFields = null, CreateIndexOptions options = null)
- {
- string collectionName = typeof(TDoc).Name;
- CreateCollection<TDoc>(collectionName, indexFields, options);
- }
- public void CreateCollection<TDoc>(string collectionName, string[] indexFields = null, CreateIndexOptions options = null)
- {
- var mongoDatabase = GetMongoDatabase();
- mongoDatabase.CreateCollection(collectionName);
- CreateIndex(GetMongoCollection<TDoc>(collectionName), indexFields, options);
- }
- public List<TDoc> Find<TDoc>(Expression<Func<TDoc, bool>> filter, FindOptions options = null)
- {
- string collectionName = typeof(TDoc).Name;
- return Find<TDoc>(collectionName, filter, options);
- }
- public List<TDoc> Find<TDoc>(string collectionName, Expression<Func<TDoc, bool>> filter, FindOptions options = null)
- {
- var colleciton = GetMongoCollection<TDoc>(collectionName);
- return colleciton.Find(filter, options).ToList();
- }
- public List<TDoc> FindByPage<TDoc, TResult>(Expression<Func<TDoc, bool>> filter, Expression<Func<TDoc, TResult>> keySelector, int pageIndex, int pageSize, out int rsCount)
- {
- string collectionName = typeof(TDoc).Name;
- return FindByPage<TDoc, TResult>(collectionName, filter, keySelector, pageIndex, pageSize, out rsCount);
- }
- public List<TDoc> FindByPage<TDoc, TResult>(string collectionName, Expression<Func<TDoc, bool>> filter, Expression<Func<TDoc, TResult>> keySelector, int pageIndex, int pageSize, out int rsCount)
- {
- var colleciton = GetMongoCollection<TDoc>(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>(TDoc doc, InsertOneOptions options = null)
- {
- string collectionName = typeof(TDoc).Name;
- Insert<TDoc>(collectionName, doc, options);
- }
- public void Insert<TDoc>(string collectionName, TDoc doc, InsertOneOptions options = null)
- {
- var colleciton = GetMongoCollection<TDoc>(collectionName);
- colleciton.InsertOne(doc, options);
- }
- public void InsertMany<TDoc>(IEnumerable<TDoc> docs, InsertManyOptions options = null)
- {
- string collectionName = typeof(TDoc).Name;
- InsertMany<TDoc>(collectionName, docs, options);
- }
- public void InsertMany<TDoc>(string collectionName, IEnumerable<TDoc> docs, InsertManyOptions options = null)
- {
- var colleciton = GetMongoCollection<TDoc>(collectionName);
- colleciton.InsertMany(docs, options);
- }
- public void Update<TDoc>(TDoc doc, Expression<Func<TDoc, bool>> filter, UpdateOptions options = null)
- {
- string collectionName = typeof(TDoc).Name;
- var colleciton = GetMongoCollection<TDoc>(collectionName);
- List<UpdateDefinition<TDoc>> updateList = BuildUpdateDefinition<TDoc>(doc, null);
- colleciton.UpdateOne(filter, Builders<TDoc>.Update.Combine(updateList), options);
- }
- public void Update<TDoc>(string collectionName, TDoc doc, Expression<Func<TDoc, bool>> filter, UpdateOptions options = null)
- {
- var colleciton = GetMongoCollection<TDoc>(collectionName);
- List<UpdateDefinition<TDoc>> updateList = BuildUpdateDefinition<TDoc>(doc, null);
- colleciton.UpdateOne(filter, Builders<TDoc>.Update.Combine(updateList), options);
- }
- public void Update<TDoc>(TDoc doc, Expression<Func<TDoc, bool>> filter, UpdateDefinition<TDoc> updateFields, UpdateOptions options = null)
- {
- string collectionName = typeof(TDoc).Name;
- Update<TDoc>(collectionName, doc, filter, updateFields, options);
- }
- public void Update<TDoc>(string collectionName, TDoc doc, Expression<Func<TDoc, bool>> filter, UpdateDefinition<TDoc> updateFields, UpdateOptions options = null)
- {
- var colleciton = GetMongoCollection<TDoc>(collectionName);
- colleciton.UpdateOne(filter, updateFields, options);
- }
- public void UpdateMany<TDoc>(TDoc doc, Expression<Func<TDoc, bool>> filter, UpdateOptions options = null)
- {
- string collectionName = typeof(TDoc).Name;
- UpdateMany<TDoc>(collectionName, doc, filter, options);
- }
- public void UpdateMany<TDoc>(string collectionName, TDoc doc, Expression<Func<TDoc, bool>> filter, UpdateOptions options = null)
- {
- var colleciton = GetMongoCollection<TDoc>(collectionName);
- List<UpdateDefinition<TDoc>> updateList = BuildUpdateDefinition<TDoc>(doc, null);
- colleciton.UpdateMany(filter, Builders<TDoc>.Update.Combine(updateList), options);
- }
- public void Delete<TDoc>(Expression<Func<TDoc, bool>> filter, DeleteOptions options = null)
- {
- string collectionName = typeof(TDoc).Name;
- Delete<TDoc>(collectionName, filter, options);
- }
- public void Delete<TDoc>(string collectionName, Expression<Func<TDoc, bool>> filter, DeleteOptions options = null)
- {
- var colleciton = GetMongoCollection<TDoc>(collectionName);
- colleciton.DeleteOne(filter, options);
- }
- public void DeleteMany<TDoc>(Expression<Func<TDoc, bool>> filter, DeleteOptions options = null)
- {
- string collectionName = typeof(TDoc).Name;
- DeleteMany<TDoc>(collectionName, filter, options);
- }
- public void DeleteMany<TDoc>(string collectionName, Expression<Func<TDoc, bool>> filter, DeleteOptions options = null)
- {
- var colleciton = GetMongoCollection<TDoc>(collectionName);
- colleciton.DeleteMany(filter, options);
- }
- public void ClearCollection<TDoc>(string collectionName)
- {
- var colleciton = GetMongoCollection<TDoc>(collectionName);
- var inddexs = colleciton.Indexes.List();
- List<IEnumerable<BsonDocument>> docIndexs = new List<IEnumerable<BsonDocument>>();
- while (inddexs.MoveNext())
- {
- docIndexs.Add(inddexs.Current);
- }
- var mongoDatabase = GetMongoDatabase();
- mongoDatabase.DropCollection(collectionName);
- if (!CollectionExists(mongoDatabase, collectionName))
- {
- CreateCollection<TDoc>(collectionName);
- }
- if (docIndexs.Count > 0)
- {
- colleciton = mongoDatabase.GetCollection<TDoc>(collectionName);
- foreach (var index in docIndexs)
- {
- foreach (IndexKeysDefinition<TDoc> 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<SysLogInfo>("SysLog1",new[]{"LogDT"});
- mongoDbHelper.Find<SysLogInfo>("SysLog1", t => t.Level == "Info");
- int rsCount=0;
- mongoDbHelper.FindByPage<SysLogInfo, SysLogInfo>("SysLog1",t=>t.Level=="Info",t=>t,1,20,out rsCount);
- mongoDbHelper.Insert<SysLogInfo>("SysLog1",new SysLogInfo { LogDT = DateTime.Now, Level = "Info", Msg = "测试消息" });
- mongoDbHelper.Update<SysLogInfo>("SysLog1",new SysLogInfo { LogDT = DateTime.Now, Level = "Error", Msg = "测试消息2" },t => t.LogDT==new DateTime(1900,1,1));
- mongoDbHelper.Delete<SysLogInfo>(t => t.Level == "Info");
- mongoDbHelper.ClearCollection<SysLogInfo>("SysLog1");
基于MongoDb官方C#驱动封装MongoDbCsharpHelper类(CRUD类)的更多相关文章
- 适用于app.config与web.config的ConfigUtil读写工具类 基于MongoDb官方C#驱动封装MongoDbCsharpHelper类(CRUD类) 基于ASP.NET WEB API实现分布式数据访问中间层(提供对数据库的CRUD) C# 实现AOP 的几种常见方式
适用于app.config与web.config的ConfigUtil读写工具类 之前文章:<两种读写配置文件的方案(app.config与web.config通用)>,现在重新整理一 ...
- 封装对MongoDB数据库的增删改查访问方法(基于MongoDB官方发布的C#驱动)
本文利用MongoDB官方发布的C#驱动,封装了对MongoDB数据库的增删改查访问方法.先用官方提供的mongo-csharp-driver ,当前版本为1.7.0.4714 编写数据库访问帮助类 ...
- 基于mongodb的python之增删改查(CRUD)
1,下载mongodb的python驱动,http://pypi.python.org/pypi/pymongo/,根据操作系统和python平台版本选择相应的egg或exe安装. 2,新建一个py脚 ...
- Go MongoDB官方数据库驱动之增删改查
package main import ( "context" "fmt" "log" "go.mongodb.org/mongo ...
- MongoDB官方C#驱动中查询条件Query用法
Query.All("name", "a", "b");//通过多个元素来匹配数组 Query.And(Query.EQ("nam ...
- MongoDB官方C#驱动的AsQueryable踩到坑了
collection.AsQueryable().Where()有4个重载,分别是: public static IQueryable<TSource> Where<TSource& ...
- 基于mongodb的java之增删改查(CRUD)
1,下载驱动https://github.com/mongodb/mongo-java-driver/downloads,导入工程java中 2,建立测试代码 import java.net.Unkn ...
- 【MongoDB】 基于C#官方驱动2.2版的封装类
一.前言 最近项目中要用到MongoDB,因此实现做了不少的调研.发现网上很多现有关于MongoDB C#官方驱动的调用方法都是基于1.8版本的,已经不是用了最新的2.2版本.因此我在基于C#官方驱动 ...
- 基于Mongodb的轻量级领域驱动框架(序)
混园子也有些年头了,从各个大牛那儿学了很多东西.技术这东西和中国的料理一样,其中技巧和经验,代代相传(这不是舌尖上的中国广告).转身回头一望,几年来自己也积累了一些东西,五花八门涉猎到各种方向,今日开 ...
随机推荐
- 选择客栈noip2011
哈,没想到吧.今天居然有两篇(算什么,厕所读物吗 选择客栈 本题的更优解请跳转zt 这题11年,刚改2day. 对于30% 的数据,有 n ≤100: 对于50% 的数据,有 n ≤1,000: 对于 ...
- java.util.ArrayList、java.util.vector和java.util.LinkedList (JDK 1.8.0_111)
一.java.util.ArrayList 1.1 ArrayList 继承结构 ArrayList实现了RandomAccess,可以随机访问(其实就是通过数组下标访问):实现了Cloneable, ...
- Java---实现邮件发送
实现发送邮件的发送必须有前提条件: 在qq邮件中开启POP3/SMTP服务,如下图所示(为本人邮件设置): 开启后会得到一个授权码.代码中会用到 需要的包: 百度网盘(包+源码):链接: https: ...
- JSP具体篇——response对象
response对象 response对象用于响应client请求,向客户输出信息. 他封装了JSP产生的响应,并发送到client以响应client请求. 1.重定向网页 使用response对象的 ...
- M03 利用Accord 进行机器学习的第一个小例子
01 安装 Visual studio 2017. 不具备安装这个的话,也可安装,Microsoft Visual Studio Express (or equivalent) 02 创建 C# 的 ...
- 自学Zabbix3.6.4-触发器triggers dependencies依赖关系
有时,一个主机的可用性取决于另一个主机.如果路由器坏了,某个路由器后面的服务器就会变得不可访问.对于两个主机都配置了触发器,您可能会收到两个主机的通知,而只有路由器是有罪的一方.这是主机之间的一些依赖 ...
- immutable.js 更新数组(mergeDeepWith)
使用情境: 技术栈为:react + redux + antd (reducer中处理数据使用了immutable.js). 问题:如下图,做一个搜索功能,form表单每改变一次,都会调用一个upda ...
- CSS实现文字换行
强制不换行:div{ white-space:nowrap; } 自动换行: div{ word-wrap:break-word; word-break:normal; } 强制不换行 white-s ...
- intellij IDEA里各图标对应的文件类型
本篇内容为大家提供的是IntelliJ IDEA 使用教程中的常见文件类型的图标介绍,IntelliJ IDEA是java语言开发的集成环境,IntelliJ在业界被公认为最好的java开发工具之一, ...
- log4go的输出优化
又看了一些golang的日志包和相关的文章,仔细阅读了go 1.9.2系统提供的log和go-log,产生了对log4go的日志输出进行优化的想法. 结构化与multiwriter log使用mult ...