Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

使用Asp.Net Core MVC 开发项目实践[第四篇:基于EF Core的扩展2]

喻平勇 2019-02-25 15:11:00 阅读数:204 评论数:0 点赞数:0 收藏数:0

上篇我们说到了基于EFCore的基础扩展,这篇我们讲解下基于实体结合拉姆达表达式的自定义更新以及删除数据.

先说下原理:其实通过实体以及拉姆达表达式生成SQL语句去执行

第一种更新扩展:

自定义更新字段以及自定义扩展条件,请看下面的代码1 ///

2 ///自定义更新扩展3 /// 4 /// 5 /// 6 /// 更新字段 7 /// 更新条件 8 /// 9 public static bool MangoUpdate(this DbContext context, Expression> fields, Expression> predicate) where TEntity : class, new()10 {11 TSqlAssembledResult result = TSqlAssembled.Update(fields, predicate);12 context.Database.ExecuteSqlCommand(result.SqlStr);13 return context.SaveChanges() > 0 ? true : false;14 }

从上面的方法中我们看到几个参数,第一个参数不必说,扩展方法第一个参数必须要的,我们重点讲清楚一下第二个和第三个参数.

参数:Expression> fields

表示实体中需要更新的字段,这里的参数要求的是一个拉姆达表达式,如下面的代码:

m => m.ClickCount == m.ClickCount + 1

这里就是更新字段ClickCount+1的功能.

参数:Expression> predicate

表示更新条件,这个参数也是一个拉姆达表达式,如下面代码:

m => m.NavigationId == navigationId

这里表示更新条件 NavigationId指定值的数据库记录.

接下来我们看方法中的调用TSqlAssembled.Update(fields, predicate);

这个方法表示将参数解析成SQL语句,我们看看这个方法的具体内容:

1 ///

2 ///更新语句组装3 /// 4 /// 5 /// 6 /// 7 /// 8 public static TSqlAssembledResult Update(Expression> fields, Expression> predicate) where TEntity : class, new()9 {10 try 11 {12 StringBuilder strBuilder = newStringBuilder();13 strBuilder.Append("update");14 strBuilder.Append(typeof(TEntity).Name);15 strBuilder.Append("set");16 //解析需要更新的字段值 17 UpdateFieldBuilder updateFieldBuilder = newUpdateFieldBuilder();18 strBuilder.Append(updateFieldBuilder.Translate(fields));19 //解析条件 20 ConditionBuilder conditionBuilder = newConditionBuilder();21 strBuilder.Append("where");22 strBuilder.Append(conditionBuilder.Translate(predicate));23 //处理结果返回 24 TSqlAssembledResult result = newTSqlAssembledResult();25 result.SqlParameters = null;26 result.SqlStr =strBuilder.ToString();27 returnresult;28 }29 catch(Exception ex)30 {31 return null;32 throwex;33 }34 }

PS:这个方法中用到的条件编译类以及字段编辑类我们将在文章底部贴出来.

第二种更新扩展:///

///自定义更新扩展/// /// /// /// 更新实体 /// 更新条件 /// public static bool MangoUpdate(this DbContext context, TEntity entity, Expression> predicate) where TEntity:class,new() { TSqlAssembledResult result= TSqlAssembled.Update(entity, predicate); context.Database.ExecuteSqlCommand(result.SqlStr, result.SqlParameters);return context.SaveChanges() > 0 ? true : false; }

参数 TEntity entity表示需要更新的实体

参数 Expression> predicate 表示更新条件,示例如下:m => m.NavigationId == navigationId

TSqlAssembled.Update(entity, predicate) 这个方法表示将参数解析成SQL语句,我们看看这个方法的具体内容:

///

///更新语句组装/// /// /// /// /// public static TSqlAssembledResult Update(TEntity entity, Expression> predicate) where TEntity : class, new() {try{ StringBuilder strBuilder= newStringBuilder(); strBuilder.Append("update");// Type type =entity.GetType(); strBuilder.Append(type.Name); strBuilder.Append("set");//处理实体类属性 PropertyInfo[] properties =type.GetProperties();int index = 0; List sqlParameter = new List();foreach (var property inproperties) {object value = property.GetValue(entity, null);if (value != null) {if (index != 0) { strBuilder.Append(","); } strBuilder.Append(property.Name); strBuilder.Append("=@"); strBuilder.Append(property.Name); sqlParameter.Add(newSqlParameter(property.Name, value)); index++; } }//编译条件 ConditionBuilder conditionBuilder = newConditionBuilder(); strBuilder.Append("where"); strBuilder.Append(conditionBuilder.Translate(predicate));//处理结果返回 TSqlAssembledResult result = newTSqlAssembledResult(); result.SqlParameters=sqlParameter.ToArray(); result.SqlStr=strBuilder.ToString();returnresult; }catch(Exception ex) {return null;throwex; } }

PS:这里我们多了将实体反射获取需要更新的字段以及字段值.

第三种删除扩展:

自定删除条件,代码如下1 ///

2 ///自定义删除扩展3 /// 4 /// 5 /// 6 /// 删除条件 7 /// 8 public static bool MangoRemove(this DbContext context,Expression> predicate) where TEntity : class,new()9 {10 TSqlAssembledResult result = TSqlAssembled.Delete(predicate);11 context.Database.ExecuteSqlCommand(result.SqlStr);12 return context.SaveChanges() > 0 ? true : false;13 }

参数Expression> predicate表示为自定义条件,示例如下:

dbContext.MangoRemovePostsAnswerRecords>(m => m.AnswerId == model.AnswerId && m.UserId == model.UserId);

PS:此段代码表示根据指定条件删除m_PostsAnswerRecords表中的记录

TSqlAssembled.Delete(predicate)方法负责将指定条件编译成SQL语句,代码如下:///

///删除语句组装/// /// /// /// public static TSqlAssembledResult Delete(Expression> predicate) where TEntity:class,new() {try{string tableName = typeof(TEntity).Name;//条件编译 ConditionBuilder conditionBuilder = newConditionBuilder();string conditionStr =conditionBuilder.Translate(predicate); StringBuilder strBuilder= newStringBuilder(); strBuilder.Append("delete from"); strBuilder.Append(tableName); strBuilder.Append("where"); strBuilder.Append(conditionStr);//处理结果返回 TSqlAssembledResult result = newTSqlAssembledResult(); result.SqlParameters= null; result.SqlStr=strBuilder.ToString();returnresult; }catch(Exception ex) {throwex; } }

下面我们贴出字段以及条件的拉姆达表达式解析类:

条件解析类(ConditionBuilder):1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Text;4 usingSystem.Linq;5 usingSystem.Linq.Expressions;6 usingSystem.Reflection;7 namespaceMango.Framework.EFCore8 {9 public classConditionBuilder : ExpressionVisitor10 {11 12 StringBuilder strBuilder;13 14 publicConditionBuilder()15 {16 }17 18 public stringTranslate(Expression expression)19 {20 this.strBuilder = newStringBuilder();21 this.Visit(expression);22 return this.strBuilder.ToString();23 }24 25 private staticExpression StripQuotes(Expression e)26 {27 while (e.NodeType ==ExpressionType.Quote)28 {29 e =((UnaryExpression)e).Operand;30 }31 returne;32 }33 34 protected overrideExpression VisitBinary(BinaryExpression b)35 {36 strBuilder.Append("(");37 this.Visit(b.Left);38 switch(b.NodeType)39 {40 caseExpressionType.AndAlso:41 strBuilder.Append("and");42 break;43 caseExpressionType.OrElse:44 strBuilder.Append("or");45 break;46 caseExpressionType.Equal:47 strBuilder.Append("=");48 break;49 caseExpressionType.NotEqual:50 strBuilder.Append("<>");51 break;52 caseExpressionType.LessThan:53 strBuilder.Append("<");54 break;55 caseExpressionType.LessThanOrEqual:56 strBuilder.Append("<=");57 break;58 caseExpressionType.GreaterThan:59 strBuilder.Append(">");60 break;61 caseExpressionType.GreaterThanOrEqual:62 strBuilder.Append(">=");63 break;64 default:65 throw new NotSupportedException(string.Format("运算符{0}不支持", b.NodeType));66 }67 if (b.Right.NodeType != ExpressionType.Parameter&& b.Right.NodeType ==ExpressionType.MemberAccess)68 {69 LambdaExpression lambda =Expression.Lambda(b.Right);70 var fn =lambda.Compile();71 this.Visit(Expression.Constant(fn.DynamicInvoke(null), b.Right.Type));72 }73 else 74 {75 this.Visit(b.Right);76 }77 strBuilder.Append(")");78 returnb;79 }80 81 protected overrideExpression VisitConstant(ConstantExpression c)82 {83 switch(Type.GetTypeCode(c.Value.GetType()))84 {85 caseTypeCode.Boolean:86 strBuilder.Append(((bool)c.Value) ? 1 : 0);87 break;88 caseTypeCode.String:89 strBuilder.Append("'");90 strBuilder.Append(c.Value);91 strBuilder.Append("'");92 break;93 caseTypeCode.Object:94 throw new NotSupportedException(string.Format("常量{0}不支持", c.Value));95 default:96 strBuilder.Append(c.Value);97 break;98 }99 returnc;100 }101 102 protected overrideExpression VisitMember(MemberExpression m)103 {104 if (m.Expression != null && m.Expression.NodeType ==ExpressionType.Parameter)105 {106 strBuilder.Append(m.Member.Name);107 returnm;108 }109 else if (m.Expression != null && m.Expression.NodeType ==ExpressionType.Constant)110 {111 LambdaExpression lambda =Expression.Lambda(m);112 var fn =lambda.Compile();113 this.Visit(Expression.Constant(fn.DynamicInvoke(null), m.Type));114 returnm;115 }116 throw new NotSupportedException(string.Format("成员{0}不支持", m.Member.Name));117 }118 }119 }

更新字段解析类(UpdateFieldBuilder):

1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Text;4 usingSystem.Linq;5 usingSystem.Linq.Expressions;6 usingSystem.Reflection;7 namespaceMango.Framework.EFCore8 {9 public classUpdateFieldBuilder : ExpressionVisitor10 {11 StringBuilder strBuilder;12 public stringTranslate(Expression expression)13 {14 this.strBuilder = newStringBuilder();15 this.Visit(expression);16 return this.strBuilder.ToString();17 }18 19 private staticExpression StripQuotes(Expression e)20 {21 while (e.NodeType ==ExpressionType.Quote)22 {23 e =((UnaryExpression)e).Operand;24 }25 returne;26 }27 protected overrideExpression VisitBinary(BinaryExpression b)28 {29 //strBuilder.Append("("); 30 this.Visit(b.Left);31 switch(b.NodeType)32 {33 caseExpressionType.Equal:34 strBuilder.Append("=");35 break;36 caseExpressionType.AndAlso:37 strBuilder.Append(",");38 break;39 caseExpressionType.Add:40 strBuilder.Append("+");41 break;42 caseExpressionType.Subtract:43 strBuilder.Append("-");44 break;45 default:46 throw new NotSupportedException(string.Format("运算符{0}不支持", b.NodeType));47 }48 this.Visit(b.Right);49 //strBuilder.Append(")"); 50 returnb;51 }52 53 protected overrideExpression VisitConstant(ConstantExpression c)54 {55 switch(Type.GetTypeCode(c.Value.GetType()))56 {57 caseTypeCode.Boolean:58 strBuilder.Append(((bool)c.Value) ? 1 : 0);59 break;60 caseTypeCode.String:61 strBuilder.Append("'");62 strBuilder.Append(c.Value);63 strBuilder.Append("'");64 break;65 caseTypeCode.Object:66 throw new NotSupportedException(string.Format("常量{0}不支持", c.Value));67 default:68 strBuilder.Append(c.Value);69 break;70 }71 returnc;72 }73 74 protected overrideExpression VisitMember(MemberExpression m)75 {76 if (m.Expression != null && m.Expression.NodeType ==ExpressionType.Parameter)77 {78 strBuilder.Append(m.Member.Name);79 returnm;80 }81 throw new NotSupportedException(string.Format("成员{0}不支持", m.Member.Name));82 }83 }84 }

到此本篇章完成,更详细的代码请下载源代码查看.

版权声明
本文为[喻平勇]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/51core/p/10431025.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;

支付宝红包,每日可领