sqlsugar入门(4)-修改源码支持多主键保存ISaveable
1.查看其它接口发现少了一个最重要的SaveBuilder。此文件是存放sql模板,where条件,select解析,组装成tosqlstring的最后一个类。
添加文件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions; namespace SqlSugar
{
public class SaveBuilder : IDMLBuilder
{
public SaveBuilder()
{
this.sql = new StringBuilder();
this.DbColumnInfoList = new List<DbColumnInfo>();
this.SetValues = new List<KeyValuePair<string, string>>();
this.WhereValues = new List<string>();
this.Parameters = new List<SugarParameter>();
}
public SqlSugarProvider Context { get; set; }
public ILambdaExpressions LambdaExpressions { get; set; }
public ISqlBuilder Builder { get; set; }
public StringBuilder sql { get; set; }
public List<SugarParameter> Parameters { get; set; }
public string TableName { get; set; }
public string TableWithString { get; set; }
public List<DbColumnInfo> DbColumnInfoList { get; set; }
public List<string> WhereValues { get; set; }
public List<KeyValuePair<string, string>> SetValues { get; set; }
public bool IsNoUpdateNull { get; set; }
public bool IsNoUpdateDefaultValue { get; set; }
public List<string> PrimaryKeys { get; set; }
public bool IsOffIdentity { get; set; }
public bool IsWhereColumns { get; set; } /// <summary>
/// select x as X as a join T t on a.id = t.id
/// </summary> public virtual string SqlTemplate
{
get
{
return @"UPDATE {0} SET
{1} {2}"; }
} public virtual string SqlTemplateBatch
{
get
{
return @" SELECT {3} FROM (
{0} ) T ,{1} S WHERE {2}
; ";
}
} public virtual string SqlTemplateBatchSelect
{
get
{
return "{0} AS {1}";
}
} public virtual string SqlTemplateBatchUnion
{
get
{
return "\t\t\r\nUNION ALL ";
}
} public virtual void Clear()
{ }
public virtual string GetTableNameString
{
get
{
var result = Builder.GetTranslationTableName(TableName);
result += UtilConstants.Space;
if (this.TableWithString.HasValue())
{
result += TableWithString + UtilConstants.Space;
}
return result;
}
}
public virtual string GetTableNameStringNoWith
{
get
{
var result = Builder.GetTranslationTableName(TableName);
return result;
}
} public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType, bool isMapping = true)
{
ILambdaExpressions resolveExpress = this.LambdaExpressions;
this.LambdaExpressions.Clear();
if (this.Context.CurrentConnectionConfig.MoreSettings != null)
{
resolveExpress.PgSqlIsAutoToLower = this.Context.CurrentConnectionConfig.MoreSettings.PgSqlIsAutoToLower;
}
else
{
resolveExpress.PgSqlIsAutoToLower = true;
}
if (isMapping)
{
resolveExpress.MappingColumns = Context.MappingColumns;
resolveExpress.MappingTables = Context.MappingTables;
resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
}
resolveExpress.InitMappingInfo = Context.InitMappingInfo;
resolveExpress.RefreshMapping = () =>
{
resolveExpress.MappingColumns = Context.MappingColumns;
resolveExpress.MappingTables = Context.MappingTables;
resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
};
resolveExpress.Resolve(expression, resolveType);
this.Parameters.AddRange(resolveExpress.Parameters);
var result = resolveExpress.Result;
return result;
}
public virtual string ToSqlString()
{
if (IsNoUpdateNull)
{
DbColumnInfoList = DbColumnInfoList.Where(it => it.Value != null).ToList();
}
if (IsNoUpdateDefaultValue)
{
DbColumnInfoList = DbColumnInfoList.Where(it => it.Value.ObjToString() !=UtilMethods.DefaultForType(it.PropertyType).ObjToString()).ToList();
}
var groupList = DbColumnInfoList.GroupBy(it => it.TableId).ToList(); return TomultipleSqlString(groupList);
} protected virtual string TomultipleSqlString(List<IGrouping<int, DbColumnInfo>> groupList)
{
Check.Exception(PrimaryKeys == null || PrimaryKeys.Count == 0, " Update List<T> need Primary key"); StringBuilder batchUpdateSql = new StringBuilder(); StringBuilder updateTable = new StringBuilder(); string selectString = string.Join(",", groupList.First().Select(
it =>
{
var result = "S." + it.DbColumnName + " " + Builder.GetTranslationColumnName(it.DbColumnName);
return result;
}
)); int i = 0;
foreach (var columns in groupList)
{
var isFirst = i == 0;
if (!isFirst)
{
updateTable.Append(SqlTemplateBatchUnion);
}
updateTable.Append("\r\n SELECT " + string.Join(",", columns.Where(o=>this.PrimaryKeys.Contains(o.DbColumnName)).Select(it => string.Format(SqlTemplateBatchSelect, FormatValue(it.Value), Builder.GetTranslationColumnName(it.DbColumnName)))));
++i;
}
updateTable.Append("\r\n");
string whereString = null;
//if (this.WhereValues.HasValue())
//{
// foreach (var item in WhereValues)
// {
// var isFirst = whereString == null;
// whereString += (isFirst ? null : " AND ");
// whereString += Regex.Replace(item, "\\" + this.Builder.SqlTranslationLeft, "S." + this.Builder.SqlTranslationLeft);
// }
//}
if (PrimaryKeys.HasValue())
{
foreach (var item in PrimaryKeys)
{
var isFirst = whereString == null;
whereString += (isFirst ? null : " AND ");
whereString += string.Format("S.{0}=T.{0}", Builder.GetTranslationColumnName(item));
}
}
batchUpdateSql.AppendFormat(SqlTemplateBatch, updateTable,this.TableName , whereString, selectString); return batchUpdateSql.ToString();
} public virtual object FormatValue(object value)
{
if (value == null)
{
return "NULL";
}
else
{
var type = UtilMethods.GetUnderType(value.GetType());
if (type == UtilConstants.DateType)
{
var date = value.ObjToDate();
if (date < Convert.ToDateTime("1900-1-1"))
{
date = Convert.ToDateTime("1900-1-1");
}
return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'";
}
else if (type == UtilConstants.ByteArrayType)
{
string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", "");
return bytesString;
}
else if (type.IsEnum())
{
return Convert.ToInt64(value);
}
else if (type == UtilConstants.BoolType)
{
return value.ObjToBool() ? "1" : "0";
}
else if (type == UtilConstants.StringType || type == UtilConstants.ObjType)
{
return "N'" + value.ToString().ToSqlFilter() + "'";
}
else
{
return "N'" + value.ToString() + "'";
}
}
}
}
}
2.修改SaveableProvider<T>使单主键查询数据库改为按条件解析查询existsObjects = this.Context.Ado.SqlQuery<T>(SaveBuilder.ToSqlString()).ToList();
3.添加动态表达式来筛选更新的数据以及插入的数据。
public List<T> insertObjects
{
get
{
var isDisableMasterSlaveSeparation = this.Context.Ado.IsDisableMasterSlaveSeparation;
this.Context.Ado.IsDisableMasterSlaveSeparation = true;
List<T> result = new List<T>();
var pks = GetPrimaryKeys();
Check.Exception(pks.IsNullOrEmpty(), "Need primary key"); var pkInfo = this.EntityInfo.Columns.Where(it => it.IsIgnore == false)
.Where(it => pks.Contains(it.DbColumnName)).ToList();
if (existsObjects == null)
{
SaveBuilder.PrimaryKeys = pks;
existsObjects = this.Context.Ado.SqlQuery<T>(SaveBuilder.ToSqlString()).ToList();
}
this.Context.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation;
ParameterExpression param1 = Expression.Parameter(typeof(T), "it");
ParameterExpression param = Expression.Parameter(typeof(T), "e");
BinaryExpression mainBinaryExpression = null;
foreach (var info in pkInfo)
{
MemberExpression body = Expression.PropertyOrField(param, info.PropertyName);
MemberExpression body1 = Expression.PropertyOrField(param1, info.PropertyName);
var exp = Expression.Equal(body, body1); if (mainBinaryExpression == null)
{
mainBinaryExpression = exp;
}
else
{
mainBinaryExpression = Expression.AndAlso(mainBinaryExpression, exp);
}
}
var lambda = Expression.Lambda<Func<T, Boolean>>(mainBinaryExpression, new[] { param });
Expression anyExpression = Expression.Call(
typeof(Enumerable), "Any",
new Type[] { typeof(T) },
Expression.Constant(existsObjects), lambda
);
var lambda1 = Expression.Lambda<Func<T, Boolean>>(Expression.Not(anyExpression), new[] { param1 });
return saveObjects.Where(lambda1.Compile()).ToList();
}
}
public List<T> updatObjects
{
get
{
var isDisableMasterSlaveSeparation = this.Context.Ado.IsDisableMasterSlaveSeparation;
this.Context.Ado.IsDisableMasterSlaveSeparation = true;
List<T> result = new List<T>();
var pks = GetPrimaryKeys();
Check.Exception(pks.IsNullOrEmpty(), "Need primary key"); var pkInfo = this.EntityInfo.Columns.Where(it => it.IsIgnore == false)
.Where(it => pks.Contains(it.DbColumnName)).ToList();
if (existsObjects == null)
{
SaveBuilder.PrimaryKeys = pks;
existsObjects = this.Context.Ado.SqlQuery<T>(SaveBuilder.ToSqlString()).ToList();
}
this.Context.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation;
ParameterExpression param1 = Expression.Parameter(typeof(T), "it");
ParameterExpression param = Expression.Parameter(typeof(T), "e");
BinaryExpression mainBinaryExpression = null;
foreach (var info in pkInfo)
{
MemberExpression body = Expression.PropertyOrField(param, info.PropertyName);
MemberExpression body1 = Expression.PropertyOrField(param1, info.PropertyName);
var exp = Expression.Equal(body, body1); if (mainBinaryExpression == null)
{
mainBinaryExpression = exp;
}
else
{
mainBinaryExpression = Expression.AndAlso(mainBinaryExpression, exp);
}
}
var lambda = Expression.Lambda<Func<T, Boolean>>(mainBinaryExpression, new[] { param });
Expression anyExpression = Expression.Call(
typeof(Enumerable), "Any",
new Type[] { typeof(T) },
Expression.Constant(existsObjects), lambda
);
var lambda1 = Expression.Lambda<Func<T, Boolean>>(anyExpression, new[] { param1 });
return saveObjects.Where(lambda1.Compile()).ToList();
}
}
4.添加tosql来打印生成的sql
ISaveable 添加tosql接口
List<KeyValuePair<string, List<SugarParameter>>> ToSql();
SaveableProvider实现接口
public List<KeyValuePair<string, List<SugarParameter>>> ToSql()
{
List<KeyValuePair<string, List<SugarParameter>>> sqllist = new List<KeyValuePair<string, List<SugarParameter>>>();
LoadInsertable();
LoadUpdateable();
if (insertable != null)
{
var insertsql = insertable.ToSql();
sqllist.Add(insertsql);
}
if (updateable != null)
{
var updatesql = updateable.ToSql();
sqllist.Add(updatesql);
} return sqllist;
}
Demo地址:https://gitee.com/xuanyun2018/sqlsugardemo.git
下一章节扩展分库分表功能。
sqlsugar入门(4)-修改源码支持多主键保存ISaveable的更多相关文章
- ok6410 u-boot-2012.04.01移植二修改源码支持单板
继ok6410 u-boot-2012.04.01移植一后修改代码,对ok6410单板初始化,主要包括时钟.串口.NAND.DDR等初始化.这些工作在以前的裸板程序都写了,直接拿来用.我觉得先写裸板程 ...
- 修改Cosbench源码 支持s3的 http range request 测试场景
在视频点播的业务应用场景中,用户使用了ffmpeg工具做视频实时转码用. 而ffmpeg使用range 请求.而Cosbench不支持这种测试场景,所以需要修改源码支持这种测试场景. HTTP 协议介 ...
- Windows7 64位环境6sv2.1大气传输模型修改源码添加国产高分卫星GF-1 GF-2光谱响应支持
下面开始添加国产卫星光谱响应的支持: 以下主要参考文章“6S大气传输模型修改源码添加.自定义卫星光谱响应(以HJ-1B CCD为例)”网址:http://blog.csdn.net/sam92/art ...
- 修改json源码支持datetime序列化
修改json源码支持datetime序列化 import json import datetime now = datetime.datetime.today() json.dumps(now) 抛出 ...
- Python paramiko 修改源码实现用户命令抓取
paramiko 源码修改 paramiko主要用来实现ssh客户端.服务端链接,上一节我们说到了堡垒机,堡垒机内有一个需求是“用户行为审计”,在这里我们就可以通过修改paramiko内文件的源码来实 ...
- Android5.1.1 - APK签名校验分析和修改源码绕过签名校验
Android5.1.1 - APK签名校验分析和修改源码绕过签名校验 作者:寻禹@阿里聚安全 APK签名校验分析 找到PackageParser类,该类在文件“frameworks/base/cor ...
- mvcAPI (入门 3)(源码)
mvcAPI (入门 3)(源码) http://download.csdn.net/detail/chunfang740/9078579
- element-ui 修改源码实践 --tranfer
1.element-ui 地址:https://github.com/ElemeFE/element 2.修改elelment-ui版本:2.2.2(请选择和项目相对应的版本) 3.修改内容:穿梭框组 ...
- zookeeper-如何修改源码-《每日五分钟搞定大数据》
本篇文章仅仅是起一个抛砖迎玉的作用,举一个如何修改源码的例子.文章的灵感来自 ZOOKEEPER-2784. 提一个问题先 之前的文章讲过zxid的设计,我们先复习下: zxid有64位,分成两部分: ...
随机推荐
- 推荐条+fragment
主布局 package com.example.dell.day1215; import android.support.design.widget.TabLayout; import android ...
- Android 字符串的常用操作
目录 Substring 基本语法 IndexOf 基本语法 Split 基本语法 Substring 基本语法 str.substring(","); //从第一个,号开始截取 ...
- mysql-9-limit
#进阶9:分页查询 /* 当要显示的数据,一页显示不全,需要分页提交sql请求 SELECT FROM JOIN ON WHERE GROUP BY HAVING ORDER BY LIMIT off ...
- Python练习题 045:Project Euler 017:数字英文表达的字符数累加
本题来自 Project Euler 第17题:https://projecteuler.net/problem=17 ''' Project Euler 17: Number letter coun ...
- RT Thread SPI设备 使用
后记: 之前,我把SPI的片选在Cubemx中配置成了SPI_NSS.现在我给它改为了GPIO_OUTPUT. 同时参考了别人的类似的一个操作无线模块(采用SPI设备驱动)的例子程序(清楚了RTT的 ...
- 03 . Docker数据资源管理与网络
Docker数据卷 在容器中管理数据主要有两种方式 # 数据卷(Data volumes) # 数据卷容器(Data volume containers) # 数据卷是一个可供一个或多个容器使用的特殊 ...
- Java知识系统回顾整理01基础04操作符02关系操作符
一.关系操作符 关系操作符:比较两个变量之间的关系 > 大于 >= 大于或等于 < 小于 <= 小于或等于 == 是否相等 != 是否不等 public class Hell ...
- C# 读取路径的各种方式
//1.获取模块的完整路径. string path1 = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; // ...
- 深入理解golang:Context
一.背景 在golang中,最主要的一个概念就是并发协程 goroutine,它只需用一个关键字 go 就可以开起一个协程,并运行. 一个单独的 goroutine运行,倒也没什么问题.如果是一个go ...
- golang 语言的特性
给函数传递参数的时候 map.slice.channel是按引用传递的 同一个变量不能用 := 这种方式创建并赋值两次. 一个包(package)的func .结构体类型变量如果要被外部的包调用.fu ...