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

一、前言

  最近项目中要用到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;
        }
    }
View Code

 

  然后对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();
        }
    }
}
View Code

   下面我将建一个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; }
    }
View Code

 

  测试代码:

    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;
        }
    }
View Code

 

  

 

posted @ 2016-06-07 10:08  のんきネコ  阅读(1331)  评论(1编辑  收藏  举报