MongoDBHelper + Expression+ JsonResult
using MongoDB.Driver; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; namespace MongodbTest.Common { /// <summary> /// MongoDb帮助类 /// </summary> public class MongoDbHelper { private static readonly string connStr = "mongodb://127.0.0.1:27017"; private static readonly string dbName = "test"; private static IMongoDatabase db = null; private static readonly object lockHelper = new object(); private MongoDbHelper() { } public static IMongoDatabase GetDb() { if (db == null) { lock (lockHelper) { if (db == null) { var client = new MongoClient(connStr); db = client.GetDatabase(dbName); } } } return db; } /// <summary> /// 新增 /// </summary> /// <param name="entity"></param> /// <returns></returns> public static T Insert<T>(T entity) { db = GetDb(); db.GetCollection<T>(typeof(T).Name).InsertOne(entity); return entity; } /// <summary> /// 更新数据-匿名字段 /// </summary> public static UpdateResult UpdateDef<T>(Expression<Func<T, bool>> filter, dynamic t) { db = GetDb(); //要修改的字段 var list = new List<UpdateDefinition<T>>(); foreach (var tt in typeof(T).GetProperties())//实体字段 { if (tt.Name.ToLower() == "id") continue;//跳过id foreach (var item in t.GetType().GetProperties())//指定字段 { if (item.Name.ToLower() == tt.Name.ToLower()) //指定字段==实体字段 { list.Add(Builders<T>.Update.Set(item.Name, item.GetValue(t))); } } } var updatefilter = Builders<T>.Update.Combine(list); return db.GetCollection<T>(typeof(T).Name).UpdateMany(filter, updatefilter); } /// <summary> /// 更新数据 /// </summary> public static UpdateResult Update<T>(Expression<Func<T, bool>> filter, T t) { db = GetDb(); //要修改的字段 var list = new List<UpdateDefinition<T>>(); foreach (var item in t.GetType().GetProperties())//实体字段 { if (item.Name.ToLower() == "id") continue;//跳过id list.Add(Builders<T>.Update.Set(item.Name, item.GetValue(t))); } var updatefilter = Builders<T>.Update.Combine(list); return db.GetCollection<T>(typeof(T).Name).UpdateMany(filter, updatefilter); } /// <summary> /// 删除 /// </summary> /// <param name="entity"></param> /// <returns></returns> public static DeleteResult Delete<T>(Expression<Func<T, bool>> filter) { db = GetDb(); return db.GetCollection<T>(typeof(T).Name).DeleteMany(filter); } /// <summary> /// 查询所有数据 /// </summary> /// <returns></returns> public static List<T> Select<T>() { db = GetDb(); return db.GetCollection<T>(typeof(T).Name).Find(_ => true).ToList(); } /// <summary> /// 查询条件数据 /// </summary> /// <returns></returns> public static List<T> Select<T>(Expression<Func<T, bool>> filter) { db = GetDb(); return db.GetCollection<T>(typeof(T).Name).Find(filter).ToList(); } /// <summary> /// 查询分页数据 /// </summary> /// <returns></returns> public static List<T> Select<T>(Expression<Func<T, bool>> filter, Expression<Func<T, object>> order, int pageIndex, int pageSize, string ascOrDesc = "desc") { db = GetDb(); if (ascOrDesc.ToLower() == "asc") { return db.GetCollection<T>(typeof(T).Name).AsQueryable<T>().Where(filter).OrderBy(order).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList(); } else { return db.GetCollection<T>(typeof(T).Name).AsQueryable<T>().Where(filter).OrderByDescending(order).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList(); } } /// <summary> /// 查询排序数据 /// </summary> /// <returns></returns> public static List<T> Select<T>(Expression<Func<T, bool>> filter, Expression<Func<T, object>> order=null, string ascOrDesc = "desc") { db = GetDb(); if (order != null) { if (ascOrDesc.ToLower() == "asc") { return db.GetCollection<T>(typeof(T).Name).AsQueryable<T>().Where(filter).OrderBy(order).ToList(); } else { return db.GetCollection<T>(typeof(T).Name).AsQueryable<T>().Where(filter).OrderByDescending(order).ToList(); } } else{ return db.GetCollection<T>(typeof(T).Name).Find(filter).ToList(); } } } }
using MongoDB.Bson; using MongodbTest.Common; using MongodbTest.Models; using System; using System.Linq.Expressions; using System.Web.Mvc; namespace MongodbTest.Controllers { public class TagsController : BaseController { [HttpGet] public ActionResult Add() { var entity = new Tags() { Tag = "htm", BookId = "Book"}; var result= MongoDbHelper.Insert<Tags>(entity); return Json(result, JsonRequestBehavior.AllowGet); } [HttpGet] public ActionResult Update() { Expression<Func<Tags, bool>> filter = u => true; filter = filter.And(u => u.Id == new ObjectId("6511278c794131422ffc68eb")); //var entity = new Tags() { BookId = "xxxx22", Tag = "html" }; //MongoDbHelper.Update<Tags>(filter, entity); var entity2 = new { BookId = "xxxx666666",Tst="xx"}; var result= MongoDbHelper.UpdateDef(filter, entity2); return Json(result, JsonRequestBehavior.AllowGet); } [HttpGet] public ActionResult Delete() { Expression<Func<Tags, bool>> filter = u => true; filter = filter.And(u => u.Id == new ObjectId("6511278c794131422ffc68e9")); var result = MongoDbHelper.Delete<Tags>(filter); return Json(result, JsonRequestBehavior.AllowGet); } [HttpGet] public ActionResult GetAll() { var result = MongoDbHelper.Select<Tags>(); return Json(result, JsonRequestBehavior.AllowGet); } [HttpGet] public ActionResult GetBy() { Expression<Func<Tags, bool>> filter = u => true; filter = filter.And(u => u.Tag == "htm"); //Expression<Func<Tags, Book, bool>> filter = (t, b) => (t.Tag == b.Title); //filter = filter.BuildExtendSelectExpre<Tags, Book>(t => t.Tag == "html"); var result = MongoDbHelper.Select<Tags>(filter); //组装 var data = new Book() { Title = "Title1111", Tags = result }; return Json(data); } [HttpPost] public ActionResult GetPage() { Expression<Func<Tags, bool>> filter = u => true; Expression<Func<Tags, object>> order = u => u.Tag; var result = MongoDbHelper.Select<Tags>(filter, order, 1, 10); //return Json(result, JsonRequestBehavior.AllowGet); return Json(result); } } }
Expression
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Linq.Expressions; namespace MongodbTest.Common { //用法 // var predicate = PredicateBuilder.GetTrue<Student>(); //predicate = predicate.And(it => it.id.ToString().Contains(strID)); //predicate = predicate.And(it => it.Birthday.ToString().Contains(strBir)); //predicate = predicate.And(it => it.Sex.ToString().Contains(strSex)); //predicate = predicate.And(it => it.Age == 20); //var lst = db.Queryable<Student>.Where(predicate).ToList(); /// /// /// </summary> public static partial class Extention { #region 拓展AndIf与AndOr public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) { return first.AndAlso<T>(second, Expression.AndAlso); } public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) { return first.AndAlso<T>(second, Expression.OrElse); } private static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2, Func<Expression, Expression, BinaryExpression> func) { var parameter = Expression.Parameter(typeof(T)); var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter); var left = leftVisitor.Visit(expr1.Body); var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter); var right = rightVisitor.Visit(expr2.Body); return Expression.Lambda<Func<T, bool>>( func(left, right), parameter); } private class ReplaceExpressionVisitor : ExpressionVisitor { private readonly Expression _oldValue; private readonly Expression _newValue; public ReplaceExpressionVisitor(Expression oldValue, Expression newValue) { _oldValue = oldValue; _newValue = newValue; } public override Expression Visit(Expression node) { if (node == _oldValue) return _newValue; return base.Visit(node); } } /// <summary> /// 符合条件则And /// </summary> /// <typeparam name="T">实体类型</typeparam> /// <param name="left">原表达式</param> /// <param name="need">是否符合条件</param> /// <param name="right">新表达式</param> /// <returns></returns> public static Expression<Func<T, bool>> AndIf<T>(this Expression<Func<T, bool>> left, bool need, Expression<Func<T, bool>> right) { if (need) { return left.And(right); } else { return left; } } /// <summary> /// 符合条件则Or /// </summary> /// <typeparam name="T">实体类型</typeparam> /// <param name="left">原表达式</param> /// <param name="need">是否符合条件</param> /// <param name="right">新表达式</param> /// <returns></returns> public static Expression<Func<T, bool>> OrIf<T>(this Expression<Func<T, bool>> left, bool need, Expression<Func<T, bool>> right) { if (need) { return left.Or(right); } else { return left; } } #endregion #region 拓展BuildExtendSelectExpre方法 /// <summary> /// 组合继承属性选择表达式树,无拓展参数 /// TResult将继承TBase的所有属性 /// </summary> /// <typeparam name="TBase">原数据类型</typeparam> /// <typeparam name="TResult">返回类型</typeparam> /// <param name="expression">拓展表达式</param> /// <returns></returns> public static Expression<Func<TBase, TResult>> BuildExtendSelectExpre<TBase, TResult>(this Expression<Func<TBase, TResult>> expression) { return GetExtendSelectExpre<TBase, TResult, Func<TBase, TResult>>(expression); } /// <summary> /// 组合继承属性选择表达式树,1个拓展参数 /// TResult将继承TBase的所有属性 /// </summary> /// <typeparam name="TBase">原数据类型</typeparam> /// <typeparam name="T1">拓展类型1</typeparam> /// <typeparam name="TResult">返回类型</typeparam> /// <param name="expression">拓展表达式</param> /// <returns></returns> public static Expression<Func<TBase, T1, TResult>> BuildExtendSelectExpre<TBase, T1, TResult>(this Expression<Func<TBase, T1, TResult>> expression) { return GetExtendSelectExpre<TBase, TResult, Func<TBase, T1, TResult>>(expression); } /// <summary> /// 组合继承属性选择表达式树,2个拓展参数 /// TResult将继承TBase的所有属性 /// </summary> /// <typeparam name="TBase">原数据类型</typeparam> /// <typeparam name="T1">拓展类型1</typeparam> /// <typeparam name="T2">拓展类型2</typeparam> /// <typeparam name="TResult">返回类型</typeparam> /// <param name="expression">拓展表达式</param> /// <returns></returns> public static Expression<Func<TBase, T1, T2, TResult>> BuildExtendSelectExpre<TBase, T1, T2, TResult>(this Expression<Func<TBase, T1, T2, TResult>> expression) { return GetExtendSelectExpre<TBase, TResult, Func<TBase, T1, T2, TResult>>(expression); } /// <summary> /// 组合继承属性选择表达式树,3个拓展参数 /// TResult将继承TBase的所有属性 /// </summary> /// <typeparam name="TBase">原数据类型</typeparam> /// <typeparam name="T1">拓展类型1</typeparam> /// <typeparam name="T2">拓展类型2</typeparam> /// <typeparam name="T3">拓展类型3</typeparam> /// <typeparam name="TResult">返回类型</typeparam> /// <param name="expression">拓展表达式</param> /// <returns></returns> public static Expression<Func<TBase, T1, T2, T3, TResult>> BuildExtendSelectExpre<TBase, T1, T2, T3, TResult>(this Expression<Func<TBase, T1, T2, T3, TResult>> expression) { return GetExtendSelectExpre<TBase, TResult, Func<TBase, T1, T2, T3, TResult>>(expression); } /// <summary> /// 组合继承属性选择表达式树,4个拓展参数 /// TResult将继承TBase的所有属性 /// </summary> /// <typeparam name="TBase">原数据类型</typeparam> /// <typeparam name="T1">拓展类型1</typeparam> /// <typeparam name="T2">拓展类型2</typeparam> /// <typeparam name="T3">拓展类型3</typeparam> /// <typeparam name="T4">拓展类型4</typeparam> /// <typeparam name="TResult">返回类型</typeparam> /// <param name="expression">拓展表达式</param> /// <returns></returns> public static Expression<Func<TBase, T1, T2, T3, T4, TResult>> BuildExtendSelectExpre<TBase, T1, T2, T3, T4, TResult>(this Expression<Func<TBase, T1, T2, T3, T4, TResult>> expression) { return GetExtendSelectExpre<TBase, TResult, Func<TBase, T1, T2, T3, T4, TResult>>(expression); } /// <summary> /// 组合继承属性选择表达式树,5个拓展参数 /// TResult将继承TBase的所有属性 /// </summary> /// <typeparam name="TBase">原数据类型</typeparam> /// <typeparam name="T1">拓展类型1</typeparam> /// <typeparam name="T2">拓展类型2</typeparam> /// <typeparam name="T3">拓展类型3</typeparam> /// <typeparam name="T4">拓展类型4</typeparam> /// <typeparam name="T5">拓展类型5</typeparam> /// <typeparam name="TResult">返回类型</typeparam> /// <param name="expression">拓展表达式</param> /// <returns></returns> public static Expression<Func<TBase, T1, T2, T3, T4, T5, TResult>> BuildExtendSelectExpre<TBase, T1, T2, T3, T4, T5, TResult>(this Expression<Func<TBase, T1, T2, T3, T4, T5, TResult>> expression) { return GetExtendSelectExpre<TBase, TResult, Func<TBase, T1, T2, T3, T4, T5, TResult>>(expression); } /// <summary> /// 组合继承属性选择表达式树,6个拓展参数 /// TResult将继承TBase的所有属性 /// </summary> /// <typeparam name="TBase">原数据类型</typeparam> /// <typeparam name="T1">拓展类型1</typeparam> /// <typeparam name="T2">拓展类型2</typeparam> /// <typeparam name="T3">拓展类型3</typeparam> /// <typeparam name="T4">拓展类型4</typeparam> /// <typeparam name="T5">拓展类型5</typeparam> /// <typeparam name="T6">拓展类型6</typeparam> /// <typeparam name="TResult">返回类型</typeparam> /// <param name="expression">拓展表达式</param> /// <returns></returns> public static Expression<Func<TBase, T1, T2, T3, T4, T5, T6, TResult>> BuildExtendSelectExpre<TBase, T1, T2, T3, T4, T5, T6, TResult>(this Expression<Func<TBase, T1, T2, T3, T4, T5, T6, TResult>> expression) { return GetExtendSelectExpre<TBase, TResult, Func<TBase, T1, T2, T3, T4, T5, T6, TResult>>(expression); } /// <summary> /// 组合继承属性选择表达式树,7个拓展参数 /// TResult将继承TBase的所有属性 /// </summary> /// <typeparam name="TBase">原数据类型</typeparam> /// <typeparam name="T1">拓展类型1</typeparam> /// <typeparam name="T2">拓展类型2</typeparam> /// <typeparam name="T3">拓展类型3</typeparam> /// <typeparam name="T4">拓展类型4</typeparam> /// <typeparam name="T5">拓展类型5</typeparam> /// <typeparam name="T6">拓展类型6</typeparam> /// <typeparam name="T7">拓展类型7</typeparam> /// <typeparam name="TResult">返回类型</typeparam> /// <param name="expression">拓展表达式</param> /// <returns></returns> public static Expression<Func<TBase, T1, T2, T3, T4, T5, T6, T7, TResult>> BuildExtendSelectExpre<TBase, T1, T2, T3, T4, T5, T6, T7, TResult>(this Expression<Func<TBase, T1, T2, T3, T4, T5, T6, T7, TResult>> expression) { return GetExtendSelectExpre<TBase, TResult, Func<TBase, T1, T2, T3, T4, T5, T6, T7, TResult>>(expression); } /// <summary> /// 组合继承属性选择表达式树,8个拓展参数 /// TResult将继承TBase的所有属性 /// </summary> /// <typeparam name="TBase">原数据类型</typeparam> /// <typeparam name="T1">拓展类型1</typeparam> /// <typeparam name="T2">拓展类型2</typeparam> /// <typeparam name="T3">拓展类型3</typeparam> /// <typeparam name="T4">拓展类型4</typeparam> /// <typeparam name="T5">拓展类型5</typeparam> /// <typeparam name="T6">拓展类型6</typeparam> /// <typeparam name="T7">拓展类型7</typeparam> /// <typeparam name="T8">拓展类型8</typeparam> /// <typeparam name="TResult">返回类型</typeparam> /// <param name="expression">拓展表达式</param> /// <returns></returns> public static Expression<Func<TBase, T1, T2, T3, T4, T5, T6, T7, T8, TResult>> BuildExtendSelectExpre<TBase, T1, T2, T3, T4, T5, T6, T7, T8, TResult>(this Expression<Func<TBase, T1, T2, T3, T4, T5, T6, T7, T8, TResult>> expression) { return GetExtendSelectExpre<TBase, TResult, Func<TBase, T1, T2, T3, T4, T5, T6, T7, T8, TResult>>(expression); } /// <summary> /// 组合继承属性选择表达式树,9个拓展参数 /// TResult将继承TBase的所有属性 /// </summary> /// <typeparam name="TBase">原数据类型</typeparam> /// <typeparam name="T1">拓展类型1</typeparam> /// <typeparam name="T2">拓展类型2</typeparam> /// <typeparam name="T3">拓展类型3</typeparam> /// <typeparam name="T4">拓展类型4</typeparam> /// <typeparam name="T5">拓展类型5</typeparam> /// <typeparam name="T6">拓展类型6</typeparam> /// <typeparam name="T7">拓展类型7</typeparam> /// <typeparam name="T8">拓展类型8</typeparam> /// <typeparam name="T9">拓展类型9</typeparam> /// <typeparam name="TResult">返回类型</typeparam> /// <param name="expression">拓展表达式</param> /// <returns></returns> public static Expression<Func<TBase, T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>> BuildExtendSelectExpre<TBase, T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(this Expression<Func<TBase, T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>> expression) { return GetExtendSelectExpre<TBase, TResult, Func<TBase, T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>>(expression); } #endregion #region 私有成员 private static Expression<TDelegate> GetExtendSelectExpre<TBase, TResult, TDelegate>(Expression<TDelegate> expression) { NewExpression newBody = Expression.New(typeof(TResult)); MemberInitExpression oldExpression = (MemberInitExpression)expression.Body; ParameterExpression[] oldParamters = expression.Parameters.ToArray(); List<string> existsProperties = new List<string>(); oldExpression.Bindings.ToList().ForEach(aBinding => { existsProperties.Add(aBinding.Member.Name); }); List<MemberBinding> newBindings = new List<MemberBinding>(); typeof(TBase).GetProperties().Where(x => !existsProperties.Contains(x.Name)).ToList().ForEach(aProperty => { if (typeof(TResult).GetMembers().Any(x => x.Name == aProperty.Name)) { MemberBinding newMemberBinding = null; var valueExpre = Expression.Property(oldParamters[0], aProperty.Name); if (typeof(TBase).IsAssignableFrom(typeof(TResult))) { newMemberBinding = Expression.Bind(aProperty, valueExpre); } else { newMemberBinding = Expression.Bind(typeof(TResult).GetProperty(aProperty.Name), valueExpre); } newBindings.Add(newMemberBinding); } }); newBindings.AddRange(oldExpression.Bindings); var body = Expression.MemberInit(newBody, newBindings.ToArray()); var resExpression = Expression.Lambda<TDelegate>(body, oldParamters); return resExpression; } #endregion } /// <summary> /// 继承ExpressionVisitor类,实现参数替换统一 /// </summary> internal class ParameterReplaceVisitor : System.Linq.Expressions.ExpressionVisitor { public ParameterReplaceVisitor(ParameterExpression paramExpr) { _parameter = paramExpr; } //新的表达式参数 private readonly ParameterExpression _parameter; protected override Expression VisitParameter(ParameterExpression p) { if (p.Type == _parameter.Type) { return _parameter; } else { return p; } } } }
JsonResult
using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using System; using System.IO; using System.Web; using System.Web.Mvc; namespace MongodbTest.Common { /// <summary> /// 继承JsonResut,重写序列化方式 /// </summary> public class JsonNetResult : JsonResult { public JsonSerializerSettings Settings { get; private set; } public JsonNetResult() { Settings = new JsonSerializerSettings { //这句是解决问题的关键,也就是json.net官方给出的解决配置选项. ReferenceLoopHandling = ReferenceLoopHandling.Ignore,//这种方式指定忽略循环引用,是在指定循环级数后忽略,返回的json数据中还是有部分循环的数据 DateFormatString = "yyyy-MM-dd HH:mm:ss", ContractResolver = new CamelCasePropertyNamesContractResolver()//json中属性开头字母小写的驼峰命名 }; } public override void ExecuteResult(ControllerContext context) { if (context == null) throw new ArgumentNullException("context"); if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) { this.JsonRequestBehavior = JsonRequestBehavior.AllowGet; //throw new InvalidOperationException("JSON GET is not allowed"); } HttpResponseBase response = context.HttpContext.Response; response.ContentType = string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType; if (this.ContentEncoding != null) response.ContentEncoding = this.ContentEncoding; if (this.Data == null) return; var scriptSerializer = JsonSerializer.Create(this.Settings); using (var sw = new StringWriter()) { scriptSerializer.Serialize(sw, this.Data); response.Write(sw.ToString()); } } } }
using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web; using System.Web.Mvc; namespace MongodbTest.Common { public class BaseController: Controller { ///// <summary> ///// json 处理 ///// </summary> ///// <param name="obj"></param> ///// <returns></returns> //public new JsonResult Json(object obj) //{ // //可使用配置处理 // string json = JsonConvert.SerializeObject(obj, new JsonSerializerSettings // { // ReferenceLoopHandling = ReferenceLoopHandling.Ignore,//这种方式指定忽略循环引用,是在指定循环级数后忽略,返回的json数据中还是有部分循环的数据 // DateFormatString = "yyyy-MM-dd HH:mm:ss", // ContractResolver = new CamelCasePropertyNamesContractResolver()//json中属性开头字母小写的驼峰命名 // }); // //object data = new // //{ // // data = json // //}; // return base.Json(json, JsonRequestBehavior.AllowGet); //} /// <summary> /// 隐藏父类,Json方法,使之返回JsonNetResult类型 /// </summary> protected new JsonResult Json(object data) { return new JsonNetResult { Data = data, }; } /// <summary> /// 隐藏父类,Json方法,使之返回JsonNetResult类型 /// </summary> protected new JsonResult Json(object data, string contentType) { return new JsonNetResult { Data = data, ContentType = contentType, }; } /// <summary> /// 重写,Json方法,使之返回JsonNetResult类型 /// </summary> protected override JsonResult Json(object data, string contentType, Encoding contentEncoding) { return new JsonNetResult { Data = data, ContentType = contentType, ContentEncoding = contentEncoding, }; } /// <summary> /// 重写,Json方法,使之返回JsonNetResult类型 /// </summary> protected override JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior) { return new JsonNetResult { Data = data, ContentType = contentType, ContentEncoding = contentEncoding, JsonRequestBehavior = behavior, }; } } }
NET Framework 4.8 (web api 项目) MongoDB.Driver(2.21.0) + Newtonsoft.Json(12.0.2) https://github.com/chxl800/MongodbTest.git