近期工作中有使用到 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类)的更多相关文章

  1. 适用于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通用)>,现在重新整理一 ...

  2. 封装对MongoDB数据库的增删改查访问方法(基于MongoDB官方发布的C#驱动)

    本文利用MongoDB官方发布的C#驱动,封装了对MongoDB数据库的增删改查访问方法.先用官方提供的mongo-csharp-driver ,当前版本为1.7.0.4714 编写数据库访问帮助类 ...

  3. 基于mongodb的python之增删改查(CRUD)

    1,下载mongodb的python驱动,http://pypi.python.org/pypi/pymongo/,根据操作系统和python平台版本选择相应的egg或exe安装. 2,新建一个py脚 ...

  4. Go MongoDB官方数据库驱动之增删改查

    package main import ( "context" "fmt" "log" "go.mongodb.org/mongo ...

  5. MongoDB官方C#驱动中查询条件Query用法

    Query.All("name", "a", "b");//通过多个元素来匹配数组 Query.And(Query.EQ("nam ...

  6. MongoDB官方C#驱动的AsQueryable踩到坑了

    collection.AsQueryable().Where()有4个重载,分别是: public static IQueryable<TSource> Where<TSource& ...

  7. 基于mongodb的java之增删改查(CRUD)

    1,下载驱动https://github.com/mongodb/mongo-java-driver/downloads,导入工程java中 2,建立测试代码 import java.net.Unkn ...

  8. 【MongoDB】 基于C#官方驱动2.2版的封装类

    一.前言 最近项目中要用到MongoDB,因此实现做了不少的调研.发现网上很多现有关于MongoDB C#官方驱动的调用方法都是基于1.8版本的,已经不是用了最新的2.2版本.因此我在基于C#官方驱动 ...

  9. 基于Mongodb的轻量级领域驱动框架(序)

    混园子也有些年头了,从各个大牛那儿学了很多东西.技术这东西和中国的料理一样,其中技巧和经验,代代相传(这不是舌尖上的中国广告).转身回头一望,几年来自己也积累了一些东西,五花八门涉猎到各种方向,今日开 ...

随机推荐

  1. tyvj4865 天天和树tree

    #include<bits/stdc++.h> #define MAXN 100000+10 using namespace std; *MAXN]; ,head[MAXN],pre[MA ...

  2. springBoot actuator监控配置及使用

    准备环境: 一个springBoot工程 第一步:添加以下依赖 <dependency> <groupId>org.springframework.boot</group ...

  3. js 匹配2个字符串相似度

    strSimilarity2Number: function (s, t) { var n = s.length, m = t.length, d = []; var i, j, s_i, t_j, ...

  4. 自己动手写http服务器——主程序(三)

    功能:目前只支持对资源的访问. 使用的模型:多线程加epoll,与传统的一个连接请求一个线程处理不同的是,这个模型只为那些需要服务的连接请求调用线程进行处理, 整个模型的大致流程 创建一个线程持对象, ...

  5. Android应用开发allowBackup敏感信息泄露的一点反思

    1 背景 [工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处.尊重劳动成果] 事实上这篇文章可能有些小题大作,但回过头想想还是非常有必要的,有点阴沟里翻船的感觉. ...

  6. JavaScript 插件的书页翻转效果

    Flipbooks书页面翻转成为在网页设计中最流行的交互动画之中的一个. 他们能够用在 Flash,网页或者在线杂志中.使用书页动画或者页面翻转的网页设计效果展示他们的产品,更加直观有效. 结合 HT ...

  7. JVM垃圾收集相关经常使用參数

    參 数 描 述 UseSerialGC 虚拟机执行在Client 模式下的默认值,打开此开关后,使用Serial + Serial Old 的收集器组合进行内存回收 UseParNewGC 打开此开关 ...

  8. centos6.5安装禅道

    1.安装禅道需要安装以下环境 mysql php 5 apache 2 2.安装命令 1.安装mysql yum install mysql mysql-server 2.安装apache yum i ...

  9. Effective Java 第三版——8. 避免使用Finalizer和Cleaner机制

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  10. 《写给大家看的设计书(第3版)》【PDF】下载

    <写给大家看的设计书(第3版)>[PDF]下载链接: https://u253469.ctfile.com/fs/253469-231196355 内容简介 <写给大家看的设计书&g ...