mongdo通用類(C#版)

 

    日前從公司離職,很快,還沒休息就步入瞭如今的公司,開始跟着公司的腳步走。html

    公司的項目基本都是大數據的,因此在數據庫上大部分都是使用Mongodb和Redis,基本都是Nosql型的數據庫爲主。之前本身學着作過Mongodb和Redis的Demo,大致知道其怎麼去運用,只是沒有一個規範化的封裝和運用,單純是學習。如今有實戰項目了,就激起了我前進學習的心,趁着今天本身查了下一些資料,學習了借鑑了一些前輩的方法後本身也封裝了一個Mongdb的底層通用類,這裏分享出來跟你們一塊兒學習下。git

    這裏主要是講我封裝的底層,不涉及到Mongodb的安裝,啓動,可視化查詢等東西,後面會附上一些參考的地址供你們一塊兒學習。github

    目前mongodb提供的驅動主要有兩種:sql

    1.官網驅動  下載地址:http://github.com/mongodb/mongo-csharp-driver/downloadsmongodb

           2.第三方的samus驅動 下載地址:https://github.com/samus/mongodb-csharp數據庫

     兩個驅動的運用本身都有使用過,我的感受官方的驅動提供的方法比較多,用起來也比較順手,並且更新度比samus的高,因此本身使用的是官方的驅動。express

   

  

      官網驅動的簡單使用

      主要使用下面的兩個dll服務器

    MongoDB.dll          驅動的主要程序多線程

    MongoDB.GridFS.dll    用於存儲大文件。併發

      基本的增刪改查代碼以下:

   
//數據庫鏈接字符串

const string strconn = "mongodb://127.0.0.1:27017";

//數據庫名稱

const string dbName = "cnblogs";

//定義數據庫

MongoDatabase db;



/// <summary>

/// 打開數據庫連接

/// </summary>

public void GetConnection()

{

//定義Mongo服務

 Mongo mongo = new Mongo(strconn);

//打開鏈接

 mongo.Connect();

//得到數據庫cnblogs,若不存在則自動建立

 db = mongo.GetDatabase(dbName) as MongoDatabase;

}



/// <summary>

/// 添加數據

/// </summary>

public void Insert()

{

var col = db.GetCollection<Users>();

//或者 

//var col = db.GetCollection("Users");



Users users = new Users();

users.Name = "xumingxiang";

users.Sex = "man";

col.Insert(users);

}

/// <summary>

/// 更新數據

/// </summary>

public void Update()

{

var col = db.GetCollection<Users>();

//查出Name值爲xumingxiang的第一條記錄

 Users users = col.FindOne(x => x.Name == "xumingxiang");

//或者 

//Users users = col.FindOne(new Document { { "Name", "xumingxiang" } });

 users.Sex = "women";

col.Update(users, x => x.Sex == "man");

}



/// <summary>

/// 刪除數據

/// </summary>

public void Delete()

{

var col = db.GetCollection<Users>();

col.Remove(x => x.Sex == "man");

////或者

////查出Name值爲xumingxiang的第一條記錄

 //Users users = col.FindOne(x => x.Sex == "man");

//col.Remove(users);

}



/// <summary>

/// 查詢數據

/// </summary>

public void Query()

{

var col = db.GetCollection<Users>();

var query = new Document { { "Name", "xumingxiang" } };



//查詢指定查詢條件的所有數據

 var result1 = col.Find(query);

//查詢指定查詢條件的第一條數據

 var result2 = col.FindOne(query);

//查詢所有集合裏的數據

 var result3 = col.FindAll();

}
View Code

 

 

       封裝擴展使用

       1.數據庫配置文件

       考慮到一個項目裏面可能使用到不一樣的數據庫(好比:普通數據和文件數據等分別存到不一樣數據庫中),也有可能會跨服務器查詢,因此這裏首先建立一個配置文件幫助類,主要是能夠進行多個數據庫配置,知足跨服務器,跨數據的需求。

       配置格式以下:

<?xml version="1.0" encoding="utf-8" ?>
<ServiceConfig>
  <mongodbs>
    <Item dbName="myDb" hostName="mongodb://127.0.0.1:27017"></Item>
    <Item dbName="myDb1" hostName="mongodb://127.0.0.1:27017"></Item>
    <Item dbName="myDb2" hostName="mongodb://127.0.0.1:27017"></Item>
  </mongodbs>
</ServiceConfig>

 

  Xml序列化對象類   

public class ServiceConfig
    {
        [XmlArray, XmlArrayItem("Item")]
        public List<mongodbConfig> mongodbs { get; set; }
    }

    [XmlRoot]
    public class mongodbConfig
    {
        [XmlAttribute("dbName")]
        public string dbName { get; set; }
        [XmlAttribute("hostName")]
        public string hostName { get; set; }
    }
View Code

   讀取配置文件管理類

   public class ManagerConfig
    {
        public static string ConfigPath;
        //加載配置文件
        static ManagerConfig()
        {
            ConfigPath = "./config.xml";
        }
        //xml序列化後的對象
        private static ServiceConfig _settings;
        public static ServiceConfig ServiceSettings
        {
            get
            {
                return _settings ?? (_settings = Load());
            }
        }

        //加載xml序列化爲ServiceConfig對象
        static ServiceConfig Load()
        {
            if (File.Exists(ConfigPath))
            {
                using (FileStream fs = new FileStream(ConfigPath, FileMode.Open))
                {
                    XmlSerializer xs = new XmlSerializer(typeof(ServiceConfig));
                    //序列化爲一個對象
                    _settings = (ServiceConfig)xs.Deserialize(fs);
                }
            }
            else
            {
                throw new Exception("數據庫配置文件不存在,請檢查");
                //_settings = new ServiceConfig();
            }

            return _settings;
        }
    }
View Code

 

   2.實體通用接口

      mongodb中自己沒有自增ID的屬性,自帶有一個ObjectID,爲了統一每一個實體對象都有這個ID ,這裏創建一個通用接口和一個底層實體基類來進行規範化處理

      實體接口   

public interface IMongoEntity
    {
        string Id { get; }
    }
View Code

      底層實體基類   

 public class BaseModel : IMongoEntity
    {
        [BsonIgnore]
        public string Id
        {
            get
            {
                if (_id == ObjectId.Empty)
                    _id = ObjectId.GenerateNewId(DateTime.Now);
                return _id.ToString();
            }
        }
        [BsonId]
        private ObjectId _id;
    }
View Code

     實體類的例子(繼承於BaseModel類)     

public class UserEntity : BaseModel
    {
        public string UserName { get; set; }

        public int Num { get; set; }

        //MongoDB中存儲的時間是標準時間UTC +0:00  (相差了8個小時)
        [BsonDateTimeOptions(Kind = DateTimeKind.Local)]
        public DateTime PostTime { get; set; }

    }
View Code

 

  3.Mongodb通用幫助基類 (主要類)    

    public class MongodbBase<T> where T : class,IMongoEntity
    {
        protected MongoServer server = null;
        protected MongoDatabase db = null;
        protected MongoCollection<T> collection;
        protected void Init(string DbName)
        {
            var Item = ManagerConfig.ServiceSettings.mongodbs.Where(p => p.dbName == DbName).FirstOrDefault();
            if (Item == null)
            {
                throw new Exception("不存在數據庫爲: " + DbName + " 的配置對象,請檢查");
            }
            else
            {
                server = MongoDB.Driver.MongoServer.Create(Item.hostName);
                db = server.GetDatabase(Item.dbName);
                collection = db.GetCollection<T>(typeof(T).Name.Replace("Entity", ""));
            }
        }

        #region 查詢
        /// <summary>
        /// 根據ID獲取對象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public T GetModelById(string id)
        {
            return collection.FindOneById(id);
        }

        /// <summary>
        /// 獲取一條記錄(自定義條件)
        /// </summary>
        /// <returns></returns>
        public T FirstOrDefault(Expression<Func<T, bool>> expression)
        {
            MongoDB.Driver.IMongoQuery query = Query<T>.Where(expression);
            return collection.FindOne(query);
        }

        /// <summary>
        /// 獲取一條記錄
        /// </summary>
        /// <returns></returns>
        public T FirstOrDefault()
        {
            return collection.FindAll().FirstOrDefault();
        }

        /// <summary>
        /// 獲取所有
        /// </summary>
        /// <returns></returns>
        public List<T> FindAll()
        {
            return collection.FindAll().ToList();
        }

        /// <summary>
        /// 獲取所有(自定義條件)
        /// </summary>
        /// <returns></returns>
        public List<T> FindAll(Expression<Func<T, bool>> expression)
        {
            MongoDB.Driver.IMongoQuery query = Query<T>.Where(expression);
            return collection.Find(query).ToList();
        }

        /// <summary>
        /// 根據條件獲取數量
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public long GetCount(Expression<Func<T, bool>> expression = null)
        {
            if (expression == null)
            {
                return collection.Count();
            }
            else
            {
                return collection.Count(Query<T>.Where(expression));
            }
        }

        /// <summary>
        /// 根據ID判斷是否存在
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool Exists(string id)
        {
            return collection.FindOneById(id) != null;
        }

        /// <summary>
        /// 分頁
        /// </summary>
        /// <param name="PageIndex">總頁碼</param>
        /// <param name="PageSize">頁容量</param>
        /// <param name="RowCounts">總記錄數</param>
        /// <param name="expression">條件</param>
        /// <param name="IsAsc">是不是正序</param>
        /// <param name="OrderFiled">排序的字段</param>
        /// <returns></returns>
        public List<T> Page(int PageIndex, int PageSize, out  long RowCounts, Expression<Func<T, bool>> expression = null, bool IsAsc = true, params string[] OrderFiled)
        {
            MongoCursor<T> mongoCursor;

            //條件選擇
            if (expression != null)
            {
                RowCounts = collection.Find(Query<T>.Where(expression)).Count();
                mongoCursor = collection.Find(Query<T>.Where(expression));
            }
            else
            {
                RowCounts = collection.FindAll().Count();
                mongoCursor = collection.FindAll();
            }

            //排序
            if (OrderFiled != null && OrderFiled.Length > 0)
            {
                //處理主鍵字段
                for (int i = 0; i < OrderFiled.Length; i++)
                {
                    if (OrderFiled[i].Equals("id", StringComparison.CurrentCultureIgnoreCase))
                    {
                        OrderFiled[i] = "_id";
                    }
                }

                if (IsAsc)
                {
                    mongoCursor = mongoCursor.SetSortOrder(SortBy.Ascending(OrderFiled));
                }
                else
                {
                    mongoCursor = mongoCursor.SetSortOrder(SortBy.Descending(OrderFiled));
                }
            }

            return mongoCursor.SetSkip((PageIndex - 1) * PageSize).SetLimit(PageSize).ToList();
        }

        #region 效率低,暫時不用
        ///// <summary>
        ///// 分頁
        ///// </summary>
        ///// <returns></returns>
        //public List<T> Page(int PageIndex, int PageSize, out  long RowCounts, Expression<Func<T, bool>> expression = null)
        //{
        //    List<T> ret = new List<T>();
        //    IQueryable<T> queryable;
        //    //條件選擇
        //    if (expression != null)
        //    {
        //        queryable = collection.Find(Query<T>.Where(expression)).AsQueryable();
        //    }
        //    else
        //    {
        //        queryable = collection.FindAll().AsQueryable();
        //    }
        //    RowCounts = queryable.Count();
        //    ret = queryable.Skip((PageIndex - 1) * PageSize).Take(PageSize).ToList();
        //    return ret;
        //}

        ///// <summary>
        ///// 分頁
        ///// </summary>
        ///// <typeparam name="TKey"></typeparam>
        ///// <param name="PageIndex"></param>
        ///// <param name="PageSize"></param>
        ///// <param name="RowCounts"></param>
        ///// <param name="expression"></param>
        ///// <param name="orderBy"></param>
        ///// <param name="IsOrder"></param>
        ///// <returns></returns>
        //public List<T> Page<TKey>(int PageIndex, int PageSize, out  long RowCounts, Expression<Func<T, bool>> expression = null, Expression<Func<T, TKey>> orderBy = null, bool IsOrder = true)
        //{
        //    List<T> ret = new List<T>();
        //    IQueryable<T> queryable;

        //    //條件選擇
        //    if (expression != null)
        //    {
        //        queryable = collection.Find(Query<T>.Where(expression)).AsQueryable();
        //    }
        //    else
        //    {
        //        queryable = collection.FindAll().AsQueryable();
        //    }
        //    //排序
        //    if (orderBy != null)
        //    {
        //        if (IsOrder)
        //        {
        //            queryable = queryable.OrderBy(orderBy);
        //        }
        //        else
        //        {
        //            queryable = queryable.OrderByDescending(orderBy);
        //        }
        //    }
        //    RowCounts = queryable.Count();
        //    ret = queryable.Skip((PageIndex - 1) * PageSize).Take(PageSize).ToList();
        //    return ret;
        //} 
        #endregion

        #endregion

        #region 刪除


        /// <summary>
        /// 帶條件的刪除
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public void Delete(Expression<Func<T, bool>> expression)
        {
            MongoDB.Driver.IMongoQuery query = Query<T>.Where(expression);
            var result = collection.Remove(query);
        }
        /// <summary>
        /// 根據模型刪除
        /// </summary>
        /// <param name="model"></param>
        public void Delete(T model)
        {
            MongoDB.Driver.IMongoQuery query = Query<T>.Where(p => p.Id == model.Id);
            collection.Remove(query);
        }

        /// <summary>
        /// 根據ID刪除
        /// </summary>
        /// <param name="Id"></param>
        public void Delete(string Id)
        {
            MongoDB.Driver.IMongoQuery query = Query<T>.Where(p => p.Id == Id);
            collection.Remove(query);
        }

        /// <summary>
        /// 所有刪除
        /// </summary>
        /// <returns></returns>
        public void DeleteAll()
        {
            var result = collection.RemoveAll();
        }
        #endregion

        #region 添加
        /// <summary>
        /// 單模型添加
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public void Insert(T model)
        {
            var result = collection.Insert<T>(model);
        }

        /// <summary>
        /// 批量添加
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public void InsertBatch(List<T> model)
        {
            collection.InsertBatch<T>(model);

        }
        #endregion

        #region 修改
        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public void Update(T model)
        {
            var result = collection.Save<T>(model);
        }

        /// <summary>
        /// 批量修改
        /// </summary>
        /// <param name="model"></param>
        public void UpdateAll(List<T> model)
        {
            model.ForEach(e => collection.Save<T>(e));
        }
        #endregion

    }
View Code

 

     4.業務類

      當新建一個表(mongodb裏面叫作集合),須要對其進行操做,包括一些業務處理時。首先繼承MongodbBase類,而後使用Init方法初始化對象,以下面的UserServcices類

public class UserServices : MongodbBase<UserEntity>
    {
        public UserServices()
        {
            this.Init("myDb");
        }

    }
View Code

 

     5.使用    

 [TestClass]
    public class UnitTest1
    {
        Random rd = new Random();
        UserServices ubll = new UserServices();

        #region 添加
        [TestMethod]
        public void 添加()
        {
            UserEntity model = new UserEntity();
            model.UserName = "Name" + rd.Next(100, 10000);
            model.Num = rd.Next(100, 10000);
            model.PostTime = DateTime.Now;
            ubll.Insert(model);

        }

        [TestMethod]
        public void 添加複雜模型()
        {
            ComplexEntity model = new ComplexEntity();
            ComplexServices cbll = new ComplexServices();
            model.Name = "Complex";
            model.Schools = new List<School>();
            model.Schools.Add(new School()
            {
                Master = new Grade()
                {
                    Name = "Master"
                },
                Name = "School",
                Students = new List<Student>()
            });
            model.Schools[0].Students.Add(new Student() { Age = 22, Name = "張三" });
            cbll.Insert(model);
        }

        [TestMethod]
        public void 批量添加()
        {
            List<UserEntity> Data = new List<UserEntity>();
            for (int i = 0; i < 1000000; i++)
            {
                UserEntity model = new UserEntity();
                model.UserName = "Name" + rd.Next(100, 10000);
                model.Num = rd.Next(100, 10000);
                model.PostTime = DateTime.Now;
                Data.Add(model);
            }
            ubll.InsertBatch(Data);
        }
        #endregion

        #region 修改
        [TestMethod]
        public void 獲取單個對象_修改()
        {
            var model = ubll.FirstOrDefault(p => p.Id != "");
            model.UserName = "new1";
            ubll.Update(model);
        }
        [TestMethod]
        public void 批量修改()
        {
            var model = ubll.FindAll();
            for (int i = 0; i < model.Count; i++)
            {
                model[i].UserName = "Text";
            }
            ubll.UpdateAll(model);
        }
        #endregion

        #region 查詢
        [TestMethod]
        public void 獲取所有對象()
        {
            var model = ubll.FindAll();
            var count = model.Count;
        }

        [TestMethod]
        public void 獲取單個對象()
        {
            var model = ubll.FirstOrDefault();
            var count = model.PostTime;
        }

        [TestMethod]
        public void 根據ID獲取對象()
        {
            var model = ubll.GetModelById("eeef22d6-7ac6-40cd-9312-59ab15fd904a");
        }


        [TestMethod]
        public void 獲取所有對條件象_帶條件()
        {
            var model = ubll.FindAll(p => p.UserName.Contains("Name"));
            var count = model.Count;
        }

        [TestMethod]
        public void 分頁()
        {

            long Rows;
            List<UserEntity> pageDate = new List<UserEntity>();
            pageDate = ubll.Page(300, 20, out Rows, p => p.Num > 1500);
            pageDate = ubll.Page(1, 20, out Rows, null, true, "Id");
            pageDate = ubll.Page(1, 20, out Rows, null, true, "Num");
            pageDate = ubll.Page(1, 20, out Rows, p => p.Num > 1500, false, "Id");

        }


        [TestMethod]
        public void 獲取數量()
        {
            //不帶條件
            var count = ubll.GetCount();
            //帶條件
            var count1 = ubll.GetCount(p => p.Num > 5000);
        }
        #endregion

        #region 刪除
        [TestMethod]
        public void 刪除_自定義條件()
        {
            ubll.Delete(p => p.Num >= 2000);
        }
        [TestMethod]
        public void 刪除_刪除模型()
        {
            var model = ubll.FirstOrDefault();
            if (model != null)
            {
                ubll.Delete(model);
            }
        }

        [TestMethod]
        public void 刪除_根據ID刪除()
        {
            ubll.Delete("ec45ea8b-a551-46eb-ad58-1b4f5f2aab25");
        }
        [TestMethod]
        public void 刪除_刪除所有()
        {
            ubll.DeleteAll();
        }
        #endregion

        #region 其餘
        [TestMethod]
        public void 同時建立兩個對象_同一數據庫內()
        {
            LogServices Logbll = new LogServices();

            UserEntity model = new UserEntity();
            model.UserName = "Name" + rd.Next(100, 10000);
            model.Num = rd.Next(100, 10000);
            model.PostTime = DateTime.Now;
            ubll.Insert(model);

            LogEntity log = new LogEntity();
            log.UserName1 = "Name" + rd.Next(100, 10000);
            log.Num1 = rd.Next(100, 10000);
            log.PostTime1 = DateTime.Now;
            Logbll.Insert(log);


            model.UserName = "Name" + rd.Next(100, 10000);
            model.Num = rd.Next(100, 10000);
            model.PostTime = DateTime.Now;
            ubll.Insert(model);
        }

        [TestMethod]
        public void 同時建立兩個對象_不一樣一數據庫內()
        {
            Log1Services Logbll = new Log1Services();

            UserEntity model = new UserEntity();
            model.UserName = "Name" + rd.Next(100, 10000);
            model.Num = rd.Next(100, 10000);
            model.PostTime = DateTime.Now;
            ubll.Insert(model);

            LogEntity log = new LogEntity();
            log.UserName1 = "Name" + rd.Next(100, 10000);
            log.Num1 = rd.Next(100, 10000);
            log.PostTime1 = DateTime.Now;
            Logbll.Insert(log);


            model.UserName = "Name" + rd.Next(100, 10000);
            model.Num = rd.Next(100, 10000);
            model.PostTime = DateTime.Now;
            ubll.Insert(model);
        }

        [TestMethod]
        public void 當指定名稱不存在時候()
        {
            ErrorServices error = new ErrorServices();
        }
        #endregion

    }
View Code

 

  以上就是本身封裝的總體邏輯和代碼,不過這裏面還有一些不明白和不足的地方,這裏提出來,但願大神們幫我解答下:

  1.返回值問題

   在添,刪,改的使用,根據官網提供的驅動,都有一個WriteConcernResult對象返回,但是在測試中發現,這個返回的對象永遠都是null

          

 

     2.增長ID問題

     mongodb中自己沒有自增ID的屬性,自帶有一個ObjectID,若是我須要一個自增ID,是不是本身建一個ID屬性,而後在增長的時候本身控制+1?不過這樣是否性能上比較低,還要考慮多線程併發的狀況下加鎖的問題。因此不知道這塊你們是怎麼去實現的?

 

   3.分頁效率的問題

    一開始分頁我是先將結果轉爲Queryable,而後在進行操做,這個代碼裏面有這段,暫時註釋掉了,後面再博客園上看到了一個前輩的mongodb分析後,改了下分頁的方式,測試過很快,但在帶條件獲取記錄行總數的時候,發現測試300W數據下,獲取總數須要600ms的時間,不知道是我方法用錯了仍是有其餘更好的?

   

    

   最後附在幾個學習的地址

    mongodb入門:http://www.cnblogs.com/fish-li/archive/2011/06/26/2090800.html

    官網驅動介紹:http://www.cnblogs.com/zhwl/p/3421034.html

    分頁優化參考:http://www.cnblogs.com/capqueen/p/MongoDBPagination.html

 

   源碼下載戳這裏-》

相關文章
相關標籤/搜索