最近开始学习Mongodb方面的东西..
看到有很多博主都说MongoDB的第三方驱动 Samus 对Linq的支持比较好..能够降低学习的成本..所以就想从这里开始..
但是弊端在我学习了一半的时候才发现..很严重..Samus驱动对数据库的操作没有返回值..增删改都没有..只有查询有结果..
这在很多时候都不能允许的..因为我们必须知道这一步是否操作成功才能够安全的进入下一步..
不过我还是硬着头皮写完了一套增删改查的工具方法..在这里共享一下..也作为一个记录..
至于具体放在什么地方使用..就要智者见智了..譬如操作日志的存储..
废话不多说..直接上代码..
这里边有部分代码都是从别处Copy来的..但却又自成体系..有作者路过的请留言..
Entity类
EntityBase: 是所有实体对象的基类..要求所有的实体都继承于他
Person: 实体对象. 不必再定义_ID..属性必须显示定义..也就是说必须都写{get;set;} 因为我们后边有一个OrderBy的动态排序要求使用类的公共属性
/// <summary> /// 对象基类..所有对象都继承于该类 /// </summary> public class EntityBase { public string _id { get; set; } } /// <summary> /// 用户实体类 实体类里不用定义ID..基类里定义过了 <例> /// </summary> class Person : EntityBase { public Person() { //创建新对象时..直接自生产新 _ID _id = MongoUtil.NewObjectId(); } public string NN { get; set; } public int Age { get; set; } }
DBHelper类 (比较长)
增删改: 这里边Insert Delete Update都写成了扩展方法..可以直接使用
可以这样用.. Person.DB_Delete() 来删除 支持 List<Person>.DB_Delete() 删除
具体的可以仔细查看一下..
using System; using System.Collections.Generic; using System.Linq; using System.Text; using MongoDB; using MongoDB.Util; using MongoDB.GridFS; using MongoDB.Commands; using MongoDB.Results; using System.Linq.Expressions; using System.Reflection; namespace Sam { public static class MongoU { #region //Query /// <summary> /// 查找对象 /// </summary> /// <param name="document">筛选条件</param> /// <returns></returns> public static TT FindOne<TT>(Document document) where TT : EntityBase { using (Mongo mon = new Mongo(Config.ConnString)) { mon.Connect(); var table = mon.GetDatabase(Config._dbName).GetCollection<TT>(typeof(TT).Name); return table.FindOne(document); } } /// <summary> /// 查找对象 /// </summary> /// <param name="predicate">Lambda 表达式</param> /// <returns></returns> public static TT FindOne<TT>(Expression<Func<TT, bool>> predicate) where TT : EntityBase { using (Mongo mon = new Mongo(Config.ConnString)) { mon.Connect(); var table = mon.GetDatabase(Config._dbName).GetCollection<TT>(typeof(TT).Name); var result = table.Find<TT>(predicate).Documents; return result.Count() != 0 ? result.First<TT>() : null; } } /// <summary> /// 查找列表 /// </summary> /// <param name="document">筛选条件</param> /// <returns></returns> public static List<TT> Find<TT>(Document document) where TT : EntityBase { using (Mongo mon = new Mongo(Config.ConnString)) { mon.Connect(); var table = mon.GetDatabase(Config._dbName).GetCollection<TT>(typeof(TT).Name); return table.Find(document).Documents.ToList(); } } /// <summary> /// 查找列表 /// </summary> /// <param name="predicate">Lambda 表达式</param> /// <returns></returns> public static List<TT> Find<TT>(Expression<Func<TT, bool>> predicate) where TT : EntityBase { using (Mongo mon = new Mongo(Config.ConnString)) { mon.Connect(); var table = mon.GetDatabase(Config._dbName).GetCollection<TT>(typeof(TT).Name); return table.Find<TT>(predicate).Documents.ToList(); } } /// <summary> /// 分页查找 /// </summary> /// <param name="Exp1">Lambda 表达式</param> /// <param name="OrderFiled">排序列</param> /// <param name="isAsc">是否正序排列 True为Asc Flase为Desc</param> /// <param name="PageIndex">页码</param> /// <param name="PageCount">页尺寸</param> /// <returns></returns> public static List<TT> FindByPage<TT>(Expression<Func<TT, bool>> Exp1, string OrderFiled, bool isAsc, int PageIndex, int PageCount) where TT : EntityBase { using (Mongo mon = new Mongo(Config.ConnString)) { mon.Connect(); var table = mon.GetDatabase(Config._dbName).GetCollection<TT>(typeof(TT).Name); //动态属性排序 return table.Linq().Where(Exp1).OrderByDynamic<TT>(OrderFiled, isAsc).Skip((PageIndex - 1) * PageCount).Take(PageCount).ToList(); } } #endregion #region //Delete /// <summary> /// 根据规则删除 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="predicate"></param> public static void DB_Delete<TT>(this TT source) where TT : EntityBase { if (source == null) return; using (Mongo mon = new Mongo(Config.ConnString)) { mon.Connect(); var table = mon.GetDatabase(Config._dbName).GetCollection<TT>(typeof(TT).Name); table.Remove(new Document().Add("_id", source._id), true); } } /// <summary> /// 根据规则删除 /// </summary> /// <typeparam name="TT"></typeparam> /// <param name="predicate"></param> public static void DB_Delete<TT>(this List<TT> source) where TT : EntityBase { if (source == null | source.Count() == 0) return; using (Mongo mon = new Mongo(Config.ConnString)) { mon.Connect(); var table = mon.GetDatabase(Config._dbName).GetCollection<TT>(typeof(TT).Name); var list = new List<string>(); foreach (var item in source) { list.Add(item._id); } table.Remove(new Document().Add("_id", MongoDB.Op.In(list.ToArray())), true); } } public static void DB_Delete<TT>(Document document) where TT : EntityBase { using (Mongo mon = new Mongo(Config.ConnString)) { mon.Connect(); var table = mon.GetDatabase(Config._dbName).GetCollection<TT>(typeof(TT).Name); table.Remove(document, true); } } public static void DB_Delete<TT>(Expression<Func<TT,bool>> Exp1) where TT : EntityBase { using (Mongo mon = new Mongo(Config.ConnString)) { mon.Connect(); var table = mon.GetDatabase(Config._dbName).GetCollection<TT>(typeof(TT).Name); table.Remove(Exp1, true); } } #endregion #region //Modify /// <summary> /// 修改单个对象 根据_id修改 /// </summary> /// <param name="obj"></param> public static void DB_Update<TT>(this TT source) where TT : EntityBase { using (Mongo mon = new Mongo(Config.ConnString)) { mon.Connect(); var table = mon.GetDatabase(Config._dbName).GetCollection<TT>(typeof(TT).Name); table.Update(source, new { _id = source._id }, true); } } #endregion #region //Add /// <summary> /// 添加一条数据到 Mongo /// </summary> /// <typeparam name="T">添加的对象类型</typeparam> /// <param name="entity">添加的对象</param> /// <returns>操作结果 来源为判断异步任务是否因异常或者取消动作而完成,是的话返回False</returns> public static void DB_Insert<TT>(this TT source) where TT : EntityBase { using (Mongo mon = new Mongo(Config.ConnString)) { mon.Connect(); var table = mon.GetDatabase(Config._dbName).GetCollection<TT>(typeof(TT).Name); table.Insert(source, true); } } /// <summary> /// 同时添加多条数据到 Mongo /// </summary> /// <typeparam name="TT">添加的对象类型</typeparam> /// <param name="entities">对象的集合</param> /// <returns>操作结果 来源为判断异步任务是否因异常或者取消动作而完成,是的话返回False</returns> public static void DB_Insert<TT>(IEnumerable<TT> entities) where TT : EntityBase { using (Mongo mon = new Mongo(Config.ConnString)) { mon.Connect(); var table = mon.GetDatabase(Config._dbName).GetCollection<TT>(typeof(TT).Name); table.Insert(entities, true); } } #endregion } }
MongoUtil 自动生成ObjectId
静态方法: String _id= MongoUtil.NewObjectId() 可以生成出来新的不会重复Id
namespace Sam { internal static class MongoUtil { private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); private static readonly object _innerLock = new object(); private static int _counter; private static readonly byte[] _machineHash = MD5.Create().ComputeHash(Encoding.Default.GetBytes(Dns.GetHostName())); private static readonly byte[] _processId = BitConverter.GetBytes(Process.GetCurrentProcess().Id); public static string NewObjectId() { var oid = new byte[12]; var copyidx = 0; Array.Copy(_machineHash, 0, oid, copyidx, 3); copyidx += 3; Array.Copy(_processId, 0, oid, copyidx, 2); copyidx += 2; Array.Copy(BitConverter.GetBytes(GenerateTime()), 0, oid, copyidx, 4); copyidx += 4; Array.Copy(BitConverter.GetBytes(GenerateCounter()), 0, oid, copyidx, 3); StringBuilder strBuilder = new StringBuilder(); foreach (byte bt in oid) { strBuilder.AppendFormat("{0:X2}", bt); } return strBuilder.ToString().ToLower(); } private static int GenerateTime() { var now = DateTime.UtcNow; var nowtime = new DateTime(Epoch.Year, Epoch.Month, Epoch.Day,now.Hour, now.Minute, now.Second, now.Millisecond); var diff = nowtime - Epoch; return Convert.ToInt32(Math.Floor(diff.TotalMilliseconds)); } private static int GenerateCounter() { lock (_innerLock) { return _counter++; } } } }
OrderBy 或 OrderByDescending 的动态排序
public static class Extended { #region //动态排序 /// <summary> /// 动态OrderBy /// </summary> /// <typeparam name="TT">TT要求是继承了EntityBase的实体类型</typeparam> /// <param name="source">操作源</param> /// <param name="propertyStr">要用来排序的属性名</param> /// <param name="isAsc">正序排 True 倒叙排 False</param> /// <returns></returns> public static IQueryable<TT> OrderByDynamic<TT>(this IQueryable<TT> source, string propertyStr, bool isAsc) where TT : class { ParameterExpression param = Expression.Parameter(typeof(TT), "c"); PropertyInfo property = typeof(TT).GetProperty(propertyStr); Expression propertyAccessExpression = Expression.MakeMemberAccess(param, property); LambdaExpression le = Expression.Lambda(propertyAccessExpression, param); Type type = typeof(TT); MethodCallExpression resultExp = Expression.Call(typeof(Queryable), (isAsc ? "OrderBy" : "OrderByDescending"), new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(le)); return source.Provider.CreateQuery<TT>(resultExp); } #endregion }
大的框架就是这样..具体的使用时可以分层..就是老三层啦..
我这里是直接对象到数据库的操作的..
大家写的时候可以仔细弄一弄..