基于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的轻量级领域驱动框架(序)
混园子也有些年头了,从各个大牛那儿学了很多东西.技术这东西和中国的料理一样,其中技巧和经验,代代相传(这不是舌尖上的中国广告).转身回头一望,几年来自己也积累了一些东西,五花八门涉猎到各种方向,今日开 ...
随机推荐
- kali git 环境配置
kali 配置很简单,输入apt-get install git 我输入时返回了错误,执行命令dpkg --configure -a 就行了
- 异常处理第三讲,SEH(结构化异常处理),异常展开问题
异常处理第三讲,SEH(结构化异常处理),异常展开问题 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 不知道昨天有木有 ...
- Spring任务调度之SpringTask基于XML和基于注解的使用示例
使用Spring的环境要求是:JDK1.8以上.Maven3.0以上. Maven依赖 SpringTask集成在SpringContext中,所以只需要SpringContext即可. 可以使用ma ...
- jquery on的常用 用法
定义和用法 on()方法在被选元素及子元素上添加一个或多个方法. 提示:使用on方法添加的事件处理程序适用于当前及未来的元素(javascript创建的) 提示:移除事件处理程序使用off()方法,如 ...
- Qt快速上手(学习笔记四)
拖了大半年,今天终于有更新了...我自己都不好意思,最近太忙了! 今天讲一下:QML语法 一 概述 QML是一种专门用于构建用户界面的编程语言,它允许用户构建高性能,具有流畅特效的可视化应用程序,QM ...
- linux系统编程:进程间通信-fifo
进程间通信-fifo 进程间通信的还有一种方式是fifo. fifo是还有一种管道:有名管道.从名字能够看出.它也是队列. 使用fifo通信前,得先创建fifo $ mkfifo myfifo 随后仅 ...
- 家居环境监測系统设计(PC上位机版)(手机APP版待定)
下面是我的毕业设计:家居环境监測系统设计(PC上位机临时版.手机app版待定).本系统採用STC12C5A60S2单片机.结合传感器.分别对空气湿度.空气温度.气压.海拔.进水温度.出水温度.光照强度 ...
- Android使用XUtils框架上传照片(一张或多张)和文本,server接收照片和文字(无乱码)
Android上传图片,这里我使用了如今比較流行的XUtils框架.该框架能够实现文件上传.文件下载.图片缓存等等,有待研究. 以下是Android端上传的代码: xUtils.jar下载 Strin ...
- JVM垃圾收集相关经常使用參数
參 数 描 述 UseSerialGC 虚拟机执行在Client 模式下的默认值,打开此开关后,使用Serial + Serial Old 的收集器组合进行内存回收 UseParNewGC 打开此开关 ...
- Python2下载单张图片和爬取网页图片
一.需求分析 1.知道图片的url地址,将图片下载到本地. 2.知道网页地址,将图片列表中的图片全部下载到本地. 二.准备工作 1.开发系统:win7 64位. 2.开发环境:python2.7. 3 ...