一、前言
最近项目中要用到MongoDB,因此实现做了不少的调研。发现网上很多现有关于MongoDB C#官方驱动的调用方法都是基于1.8版本的,已经不是用了最新的2.2版本。因此我在基于C#官方驱动2.2的基础上,对MongoDB的调用方法做了一些封装,以便于调用。
封装的内容包括:
1.封装了获取数据库及集合的方法
2.封装了新增一条、多条数据的方法
3.封装了更新一条、根据条件更新多条数据的方法,注意:是将对象统一更新成同一内容。
4.封装了删除一条,根据条件删除多条数据的方法。
5.封装了根据Id获取单条数据,根据条件获取单条数据,获取集合首条数据的方法。
二、环境准备
1 .NET Framework:4.5
2 相关文档
入门指南:http://mongodb.github.io/mongo-csharp-driver/2.2/getting_started/quick_tour/
API文档:http://api.mongodb.org/csharp/2.2
3 使用NuGet下载最新的驱动
1)右键点击类库中【引用】,选择【管理NuGet程序包】
2)联机搜索【mongodb driver】 ,选中安装下图中的3个类库,每个类库都是必须的.
三、类库封装
首先是MongoDB对象类的基础类,所有和MongoDB打交道的类都要基于这个类。
public class MongoObj { public ObjectId _id { get; set; } /// <summary> /// 将对象属性转成字典 /// </summary> /// <returns></returns> public Dictionary<String, Object> ToMap() { Dictionary<String, Object> map = new Dictionary<string, object>(); Type t = this.GetType(); PropertyInfo[] pi = t.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo p in pi) { MethodInfo mi = p.GetGetMethod(); if (mi != null && mi.IsPublic) { map.Add(p.Name, mi.Invoke(this, new Object[] { })); } } return map; } /// <summary> /// 将对象属性转成字典,并去掉字典中的_id. /// </summary> /// <returns></returns> public Dictionary<String, Object> ToMapWithoutId() { var map = ToMap(); if (map != null && map.Keys.Contains("_id")) { map.Remove("_id"); } return map; } }
然后对MongoDB的调用方法进行封装。
using DNElecCar.Data.Models.ViewModels; 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; namespace DNElecCar.Data.Repositories { /// <summary> /// mongodb的封装类,基于Mongodb C#官方驱动2.2版。 /// </summary> public sealed class MongoRepository { public static readonly string connectionString_Default = System.Configuration.ConfigurationManager.AppSettings["sqlConnectionStringMongo"].Split(';')[0]; public static readonly string database_Default = System.Configuration.ConfigurationManager.AppSettings["sqlConnectionStringMongo"].Split(';')[1].Split('=')[1]; #region 获取数据库 public IMongoDatabase GetMongoDatabase() { return GetMongoDatabase(connectionString_Default, database_Default); } public IMongoDatabase GetMongoDatabase(string connectionString, string databaseName) { var client = new MongoClient(connectionString); var dbExists = client.ListDatabases().ToList().Any(o => o.Elements.Any(p => "name".Equals(p.Name) && databaseName.Equals(p.Value.AsString))); if (!dbExists) { throw new Exception("所请求的数据库不存在!"); } return client.GetDatabase(databaseName); } #endregion #region 获取集合 public IMongoCollection<T> GetMongoCollection<T>(string collectionName) { var myCollection = GetMongoCollection<T>(connectionString_Default, database_Default, collectionName); return myCollection; } public IMongoCollection<T> GetMongoCollection<T>(string connectionString, string databaseName, string collectionName) { var database = GetMongoDatabase(connectionString, databaseName); var collectionFilter = new BsonDocument("name", collectionName); var collections = database.ListCollections(new ListCollectionsOptions { Filter = collectionFilter }); if (!collections.ToList().Any()) { throw new Exception("所请求的集合不存在!"); } var myCollection = database.GetCollection<T>(collectionName); return myCollection; } #endregion #region 新增 public void InsertOne<T>(string collectionName, T entity) { InsertOne<T>(MongoRepository.connectionString_Default, MongoRepository.database_Default, collectionName, entity); } public void InsertOne<T>(string connectionString, string databaseName, string collectionName, T entity) { if (null == entity) return; var myCollection = GetMongoCollection<T>(connectionString, databaseName, collectionName); myCollection.InsertOne(entity); } public void InsertMany<T>(string collectionName, IEnumerable<T> entitys) { InsertMany<T>(MongoRepository.connectionString_Default, MongoRepository.database_Default, collectionName, entitys); } public void InsertMany<T>(string connectionString, string databaseName, string collectionName, IEnumerable<T> entitys) { if (null == entitys) return; var myCollection = GetMongoCollection<T>(connectionString, databaseName, collectionName); myCollection.InsertMany(entitys); } #endregion #region 修改 public void UpdateOrCreateOne<T>(string collectionName, T entity) where T : MongoObj { if ("000000000000000000000000".Equals(entity._id.ToString())) { InsertOne<T>(collectionName, entity); } else { UpdateOne<T>(collectionName, entity); } } public void UpdateOne<T>(string collectionName, T entity) where T : MongoObj { UpdateOne<T>(MongoRepository.connectionString_Default, MongoRepository.database_Default, collectionName, entity); } /// <summary> /// 更新集合属性,支持复杂类型的集合对象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="connectionString"></param> /// <param name="databaseName"></param> /// <param name="collectionName"></param> /// <param name="entity"></param> public void UpdateOne<T>(string connectionString, string databaseName, string collectionName, T entity) where T : MongoObj { var myCollection = GetMongoCollection<T>(connectionString, databaseName, collectionName); var filter = Builders<T>.Filter.Eq("_id", entity._id); var fieldList = GetUpdateDefinitions(entity); myCollection.UpdateOne(filter, Builders<T>.Update.Combine(fieldList)); } #region 递归获取字段更新表达式 private List<UpdateDefinition<T>> GetUpdateDefinitions<T>(T entity) { var type = typeof(T); var fieldList = new List<UpdateDefinition<T>>(); foreach (var property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { GenerateRecursion<T>(fieldList, property, property.GetValue(entity), entity, ""); } return fieldList; } private void GenerateRecursion<TEntity>( List<UpdateDefinition<TEntity>> fieldList, PropertyInfo property, object propertyValue, TEntity item, string father) { //复杂类型 if (property.PropertyType.IsClass && property.PropertyType != typeof(string) && propertyValue != null) { //集合 if (typeof(IList).IsAssignableFrom(propertyValue.GetType())) { foreach (var sub in property.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (sub.PropertyType.IsClass && sub.PropertyType != typeof(string)) { var arr = propertyValue as IList; if (arr != null && arr.Count > 0) { for (int index = 0; index < arr.Count; index++) { foreach (var subInner in sub.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (string.IsNullOrWhiteSpace(father)) GenerateRecursion(fieldList, subInner, subInner.GetValue(arr[index]), item, property.Name + "." + index); else GenerateRecursion(fieldList, subInner, subInner.GetValue(arr[index]), item, father + "." + property.Name + "." + index); } } } } } } //实体 else { foreach (var sub in property.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (string.IsNullOrWhiteSpace(father)) GenerateRecursion(fieldList, sub, sub.GetValue(propertyValue), item, property.Name); else GenerateRecursion(fieldList, sub, sub.GetValue(propertyValue), item, father + "." + property.Name); } } } //简单类型 else { if (property.Name != "_id")//更新集中不能有实体键_id { if (string.IsNullOrWhiteSpace(father)) fieldList.Add(Builders<TEntity>.Update.Set(property.Name, propertyValue)); else fieldList.Add(Builders<TEntity>.Update.Set(father + "." + property.Name, propertyValue)); } } } /// <summary> /// 构建Mongo的更新表达式 /// </summary> /// <param name="entity"></param> /// <returns></returns> private List<UpdateDefinition<T>> GeneratorMongoUpdate<T>(T item) { var fieldList = new List<UpdateDefinition<T>>(); foreach (var property in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)) { GenerateRecursion<T>(fieldList, property, property.GetValue(item), item, string.Empty); } return fieldList; } #endregion /// <summary> /// 更新指定条件的对象,更新结果为0,则新增一条数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="collectionName"></param> /// <param name="entity"></param> /// <param name="query"></param> public void UpdateAllOrCreateOne<T>(string collectionName, T entity, Expression<Func<T, bool>> query) where T : MongoObj { var updateResult = UpdateAll<T>(MongoRepository.connectionString_Default, MongoRepository.database_Default, collectionName, entity, query); if (updateResult.MatchedCount == 0) { InsertOne<T>(MongoRepository.connectionString_Default, MongoRepository.database_Default, collectionName, entity); } } /// <summary> /// 更新所有对象更新为同一的对象值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="collectionName"></param> /// <param name="entity">更新对象。 </param> /// <param name="query">条件查询。 调用示例:o=> o.UserName == "TestUser" 等等</param> /// <returns></returns> public UpdateResult UpdateAll<T>(string collectionName, T entity, Expression<Func<T, bool>> query) where T : MongoObj { return UpdateAll<T>(MongoRepository.connectionString_Default, MongoRepository.database_Default, collectionName, entity, query); } /// <summary> /// 更新所有对象更新为同一的对象值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="connectionString"></param> /// <param name="databaseName"></param> /// <param name="collectionName"></param> /// <param name="entity">更新对象。 </param> /// <param name="query">条件查询。 调用示例:o=> o.UserName == "TestUser" 等等</param> /// <returns></returns> public UpdateResult UpdateAll<T>(string connectionString, string databaseName, string collectionName, T entity, Expression<Func<T, bool>> query = null) where T : MongoObj { var myCollection = GetMongoCollection<T>(connectionString, databaseName, collectionName); var fieldList = GetUpdateDefinitions(entity); return myCollection.UpdateMany<T>(query, Builders<T>.Update.Combine(fieldList)); } #endregion #region 删除 public void Delete<T>(string collectionName, T entity) where T : MongoObj { Delete<T>(MongoRepository.connectionString_Default, MongoRepository.database_Default, collectionName, entity._id); } public void Delete<T>(string connectionString, string databaseName, string collectionName, ObjectId _id) { var myCollection = GetMongoCollection<T>(connectionString, databaseName, collectionName); var filter = Builders<T>.Filter.Eq("_id", _id); myCollection.DeleteOne(filter); } public void Delete<T>(string collectionName, Expression<Func<T, bool>> query) { Delete<T>(MongoRepository.connectionString_Default, MongoRepository.database_Default, collectionName, query); } public void Delete<T>(string connectionString, string databaseName, string collectionName, Expression<Func<T, bool>> query) { var myCollection = GetMongoCollection<T>(connectionString, databaseName, collectionName); if (query != null) { myCollection.DeleteManyAsync<T>(query); } } #endregion #region 获取单条信息 public T FirstOrDefault<T>(string collectionName, string _id) { return FirstOrDefault<T>(MongoRepository.connectionString_Default, MongoRepository.database_Default, collectionName, _id); } public T FirstOrDefault<T>(string connectionString, string databaseName, string collectionName, string _id) { var myCollection = GetMongoCollection<T>(connectionString, databaseName, collectionName); ObjectId id; if (!ObjectId.TryParse(_id, out id)) return default(T); var filter = Builders<T>.Filter.Eq("_id", id); return myCollection.Find<T>(filter).First(); } /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="collectionName"></param> /// <param name="query">条件查询。 调用示例:o=> o.UserName == "username" 等等</param> /// <returns></returns> public T FirstOrDefault<T>(string collectionName, Expression<Func<T, bool>> query) { return FirstOrDefault<T>(MongoRepository.connectionString_Default, MongoRepository.database_Default, collectionName, query); } /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="connectionString"></param> /// <param name="databaseName"></param> /// <param name="collectionName"></param> /// <param name="query">条件查询。 调用示例:o=> o.UserName == "username" 等等</param> /// <returns></returns> public T FirstOrDefault<T>(string connectionString, string databaseName, string collectionName, Expression<Func<T, bool>> query) { var myCollection = GetMongoCollection<T>(connectionString, databaseName, collectionName); T result = default(T); if (query != null) { result = myCollection.Find<T>(query).FirstOrDefault(); } return result; } #endregion } /// <summary> /// mongodb的封装类的拓展方法。 /// </summary> public static class MongoRepositoryExt { /// <summary> /// 获取结合的首条数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="collection"></param> /// <returns></returns> public static T FirstOne<T>(this IMongoCollection<T> collection) { return collection.AsQueryable().Take(1).FirstOrDefault(); } } }
下面我将建一个User集合,并对这个User集合进行增删改查。
Users:
public class Users : MongoObj { public string ObjectId_id { get; set; } public string Name { get; set; } public string Sex { set; get; } public List<int> Spell { get; set; } }
测试代码:
public class TestLogic { private MongoDBHelper _mongo; public TestLogic() { _mongo = new MongoDBHelper(); } public int Insert() { Users users = new Users() { Name = "test", Sex="man", Spell = new List<int>() }; users.Spell.Add(1); users.Spell.Add(2); users.Spell.Add(3); var collection = _mongo.GetMongoCollection<Users>("User"); collection.InsertOne(users); return collection.AsQueryable().Count(); } public int Delete() { var collection = _mongo.GetMongoCollection<Users>("User"); var first = collection.FirstOne<Users>(); _mongo.Delete<Users>("User", first); return collection.AsQueryable().Count(); } public int DeleteMany() { var collection = _mongo.GetMongoCollection<Users>("User"); _mongo.DeleteMany<Users>("User", o => o.Sex == "man"); return collection.AsQueryable().Count(); } public int Update() { var collection = _mongo.GetMongoCollection<Users>("User"); var first = collection.FirstOne<Users>(); first.Sex = "女"; first.Name = "Update"; first.Spell.ForEach(o => { first.Spell[first.Spell.IndexOf(o)] = o + 40; }); _mongo.UpdateOne("User", first); return collection.AsQueryable().Count(); } public string GetOne() { var user = _mongo.FirstOrDefault<Users>("User", o => o.Sex == "女"); return user == null ? "" : user.Name; } }