转载

mongdo通用类(C#版)

日前从公司离职,很快,还没休息就步入了现在的公司,开始跟着公司的脚步走。

公司的项目基本都是大数据的,所以在数据库上大部分都是使用Mongodb和Redis,基本都是Nosql型的数据库为主。以前自己学着做过Mongodb和Redis的Demo,大体知道其怎么去运用,只是没有一个规范化的封装和运用,单纯是学习。现在有实战项目了,就激起了我前进学习的心,趁着今天自己查了下一些资料,学习了借鉴了一些前辈的方法后自己也封装了一个Mongdb的底层通用类,这里分享出来跟大家一起学习下。

这里主要是讲我封装的底层,不涉及到Mongodb的安装,启动,可视化查询等东西,后面会附上一些参考的地址供大家一起学习。

目前mongodb提供的驱动主要有两种:

1.官网驱动  下载地址: http://github.com/mongodb/mongo-csharp-driver/downloads

2.第三方的 samus 驱动 下载地址: https://github.com/samus/mongodb-csharp

两个驱动的运用自己都有使用过,个人感觉官方的驱动提供的方法比较多,用起来也比较顺手,而且更新度比 samus 的高,所以自己使用的是官方的驱动。

官网驱动的简单使用

    主要使用下面的两个dll

MongoDB.dll          驱动的主要程序

MongoDB.GridFS.dll    用于存储大文件。

基本的增删改查代码如下:

mongdo通用类(C#版)
//数据库连接字符串  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序列化对象类

mongdo通用类(C#版)
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

读取配置文件管理类

mongdo通用类(C#版)
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 ,这里建立一个通用接口和一个底层实体基类来进行规范化处理

实体接口

mongdo通用类(C#版)
public interface IMongoEntity     {         string Id { get; }     }
View Code

底层实体基类

mongdo通用类(C#版)
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类)

mongdo通用类(C#版)
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通用帮助基类 (主要类)    

mongdo通用类(C#版)
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类

mongdo通用类(C#版)
public class UserServices : MongodbBase<UserEntity>     {         public UserServices()         {             this.Init("myDb");         }      }
View Code

5.使用    

mongdo通用类(C#版)
 [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

mongdo通用类(C#版)

2.增加ID问题

mongodb中本身没有自增ID的属性,自带有一个ObjectID,如果我需要一个自增ID,是否是自己建一个ID属性,然后在增加的时候自己控制+1?不过这样是否性能上比较低,还要考虑多线程并发的情况下加锁的问题。所以不知道这块大家是怎么去实现的?

3.分页效率的问题

一开始分页我是先将结果转为Queryable,然后在进行操作,这个代码里面有这段,暂时注释掉了,后面再博客园上看到了一个前辈的mongodb分析后,改了下分页的方式,测试过很快,但在带 条件获取记录行总数 的时候,发现测试 300W 数据下, 获取总数需要600ms的时间 ,不知道是我方法用错了还是有其他更好的?

mongdo通用类(C#版)

最后附在几个学习的地址

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

源码下载 :戳这里-》

正文到此结束
Loading...