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 用于存储大文件。
基本的增删改查代码如下:
//数据库连接字符串
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();
}
封装扩展使用
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; }
}
读取配置文件管理类
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;
}
}
2.实体通用接口
mongodb中本身没有自增ID的属性,自带有一个ObjectID,为了统一每个实体对象都有这个ID ,这里建立一个通用接口和一个底层实体基类来进行规范化处理
实体接口
public interface IMongoEntity
{
string Id { get; }
}
底层实体基类
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;
}
实体类的例子(继承于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; } }
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 > )
{
//处理主键字段
for (int i = ; 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 - ) * 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 }
4.业务类
当新建一个表(mongodb里面叫做集合),需要对其进行操作,包括一些业务处理时。首先继承MongodbBase类,然后使用Init方法初始化对象,如下面的UserServcices类
public class UserServices : MongodbBase<UserEntity>
{
public UserServices()
{
this.Init("myDb");
} }
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(, );
model.Num = rd.Next(, );
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[].Students.Add(new Student() { Age = , Name = "张三" });
cbll.Insert(model);
} [TestMethod]
public void 批量添加()
{
List<UserEntity> Data = new List<UserEntity>();
for (int i = ; i < ; i++)
{
UserEntity model = new UserEntity();
model.UserName = "Name" + rd.Next(, );
model.Num = rd.Next(, );
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 = ; 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(, , out Rows, p => p.Num > );
pageDate = ubll.Page(, , out Rows, null, true, "Id");
pageDate = ubll.Page(, , out Rows, null, true, "Num");
pageDate = ubll.Page(, , out Rows, p => p.Num > , false, "Id"); } [TestMethod]
public void 获取数量()
{
//不带条件
var count = ubll.GetCount();
//带条件
var count1 = ubll.GetCount(p => p.Num > );
}
#endregion #region 删除
[TestMethod]
public void 删除_自定义条件()
{
ubll.Delete(p => p.Num >= );
}
[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(, );
model.Num = rd.Next(, );
model.PostTime = DateTime.Now;
ubll.Insert(model); LogEntity log = new LogEntity();
log.UserName1 = "Name" + rd.Next(, );
log.Num1 = rd.Next(, );
log.PostTime1 = DateTime.Now;
Logbll.Insert(log); model.UserName = "Name" + rd.Next(, );
model.Num = rd.Next(, );
model.PostTime = DateTime.Now;
ubll.Insert(model);
} [TestMethod]
public void 同时创建两个对象_不同一数据库内()
{
Log1Services Logbll = new Log1Services(); UserEntity model = new UserEntity();
model.UserName = "Name" + rd.Next(, );
model.Num = rd.Next(, );
model.PostTime = DateTime.Now;
ubll.Insert(model); LogEntity log = new LogEntity();
log.UserName1 = "Name" + rd.Next(, );
log.Num1 = rd.Next(, );
log.PostTime1 = DateTime.Now;
Logbll.Insert(log); model.UserName = "Name" + rd.Next(, );
model.Num = rd.Next(, );
model.PostTime = DateTime.Now;
ubll.Insert(model);
} [TestMethod]
public void 当指定名称不存在时候()
{
ErrorServices error = new ErrorServices();
}
#endregion }
以上就是自己封装的整体逻辑和代码,不过这里面还有一些不明白和不足的地方,这里提出来,希望大神们帮我解答下:
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
源码下载:戳这里-》
mongdo通用类(C#版)的更多相关文章
- poi导出excel通用类
一.关键的通用类public class PoiExportUtils { private static HSSFWorkbook workBook; public PoiExportUtils ...
- NPOI MVC 模型导出Excel通用类
通用类: public enum DataTypeEnum { Int = , Float = , Double = , String = , DateTime = , Date = } public ...
- MVC NPOI Linq导出Excel通用类
之前写了一个模型导出Excel通用类,但是在实际应用中,可能不是直接导出模型,而是通过Linq查询后获取到最终结果再导出 通用类: public enum DataTypeEnum { Int = , ...
- NPOI导入导出EXCEL通用类,供参考,可直接使用在WinForm项目中
以下是NPOI导入导出EXCEL通用类,是在别人的代码上进行优化的,兼容xls与xlsx文件格式,供参考,可直接使用在WinForm项目中,由于XSSFWorkbook类型的Write方法限制,Wri ...
- 我写的一个ExcelHelper通用类,可用于读取或生成数据
读取或生成EXCEL数据的方法有很多,一般常见的有: 1.通过OFFICE EXCEL组件,优点:读取与生成EXCEL文件方便,缺点:服务器上必须安装OFFICE软件,且进程无法及时释放 2.通过第三 ...
- DataTable转List<Model>通用类
/// <summary> /// DataTable转List<Model>通用类[实体转换辅助类] /// </summary> public class Mo ...
- Memcached通用类(基于enyim.com Memcached Client)
一.如果用官方提供的方法,在web.config里面配置好了各个参数和服务器IP.如下图: <?xml version="1.0"?> <configuratio ...
- Memcached通用类(基于Memcached Client Library)
分享下自己编写的Memcached通用类.欢迎大家帮忙指点下哈~ 使用的是.NET memcached client library 客户端+Memcached Providers using Sys ...
- .NET基础篇——Entity Framework 数据转换层通用类
在实现基础的三层开发的时候,大家时常会在数据层对每个实体进行CRUD的操作,其中存在相当多的重复代码.为了减少重复代码的出现,通常都会定义一个共用类,实现相似的操作,下面为大家介绍一下Entity F ...
随机推荐
- 手把手搭建WAMP+PHP+SVN开发环境
一:WAMP 这款软件在安装的过程中就已经把Apache.MySQL.PHP继承好了,而且也做好了相应的配置,除此之外,还加上了SQLitemanager和Phpmyadmin,省去了很多复杂的配置过 ...
- UWP 统一平台开发介绍
什么是UWP? 很多程序员都有一个梦想:希望自己开发的软件能够轻而易举的在所有平台上运行,而不是把同样的需求,用不同的技术.工具重新开发才能够运行在所有平台上.这就是跨平台,很多软件从业者都在为这个梦 ...
- save与persist差别
唯一差别: 在没提交事务情况下 save会产生insert语句,然后因为没提交事务进行回滚. 而这种情况,persist是连insert语句都不会产生.
- Android消息机制
每一个Android应用在启动的时候都会创建一个线程,这个线程被称为主线程或者UI线程,Android应用的所有操作默认都会运行在这个线程中. 但是当我们想要进行数据请求,图片下载,或者其他耗时操作时 ...
- 使用OData技术遇到的问题及解决办法
“System.NotSupportedException”类型的未经处理的异常在 Microsoft.Data.Services.Client.dll 中发生 其他信息: 对此 POST 请求的响应 ...
- CocoaPods 使用
为什么要使用这个玩意呢,最近在使用swift开发项目,使用 swift 开源库的时候,在git上下载后居然不知道哪些是必须文件,还要思考下,看看哪些是需要的(不像原来oc开源库,一目了然),网上使用d ...
- 日志分析系统——Hangout源码学习
这两天看了下hangout的代码,虽然没有运行体验过,但是也算是学习了一点皮毛. 架构浅谈 Hangout可以说是java版的Logstash,我是没有测试过性能,不过据说是kafka这边性能要高出L ...
- iOS-国家气象局-天气预报接口等常用接口
接口地址: http://www.weather.com.cn/data/sk/101010100.html http://www.weather.com.cn/data/cityinfo/10101 ...
- eclipse导入cordova创建的项目
eclipse导入cordova创建的项目 看图不说话 run这个MainActivity就可以了,bin目录下会生成APK
- python入门学习课程推荐
最近在学习自动化,学习过程中,越来越发现coding能力的重要性,不会coding,基本不能开展自动化测试(自动化工具只是辅助). 故:痛定思痛,先花2个星期将python基础知识学习后,再进入自动化 ...