C# 数据操作系列 - 16 SqlSugar 完结篇
0. 前言
前一篇我们详细的介绍了SqlSugar的增删改查,那些已经满足我们在日常工程开发中的使用了。但是还有一点点在开发中并不常用,但是却非常有用的方法。接下来让我们一起来看看还有哪些有意思的内容。
1. 不同寻常的查询
之前介绍了针对单个表的查询,同样也是相对简单的查询模式。虽然开发完全够用,但是难免会遇到一些特殊的情况。而下面这些方法就是为了解决这些意料之外。
1.1 多表查询
SqlSugar提供了一种特殊的多表查询方案,使用IQueryable接口 。来看看是怎样操作的吧:
ISugarQueryable<T, T2> Queryable<T, T2>(Expression<Func<T, T2, object[]>> joinExpression);
ISugarQueryable<T, T2> Queryable<T, T2>(ISugarQueryable<T> joinQueryable1, ISugarQueryable<T2> joinQueryable2, Expression<Func<T, T2, bool>> joinExpression)
where T : class, new()
where T2 : class, new();
ISugarQueryable<T, T2> Queryable<T, T2>(ISugarQueryable<T> joinQueryable1, ISugarQueryable<T2> joinQueryable2, JoinType joinType, Expression<Func<T, T2, bool>> joinExpression)
where T : class, new()
where T2 : class, new();
ISugarQueryable<T, T2> Queryable<T, T2>(Expression<Func<T, T2, bool>> joinExpression) where T : class, new();
这些方法是属于SqlSugarClient类的方法,SqlSugar提供了最多12个泛型的方法支持,当然实际上开发中能遇到5个表的联查都很少。除非说是在做报表程序,否则就得审查一下数据表模型是否合理了。就以这四个方法为例,介绍一下多表查询如何使用:
先来两个模型类:
public class Person
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
public class Employee
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
public string Name { get; set; }
public int PersonId { get; set; }
[SugarColumn(IsIgnore = true)]
public Person Person { get; set; }
}
简单的描述一下两个类的关系:一个雇员身份对应一个人,但一个人不一定会有一个雇员身份。
OK,先从第一个方法说起:
var query = context.Client.Queryable<Person, Employee>((pr, em)=>new object[]
{
JoinType.Left,
em.PersonId == pr.Id
});
第一个返回,是两个表的连接方式,例如:Left代表左连接,Inner表示内连接,Right表示右连接;第二个返回是两个表之间的连接依据。这是一个固定的形式,返回一个Object数组,其中第一个是连接方式,第二个是通过哪个(些)字段进行连接。
生成的SQL类似如下:
SELECT `pr`.`Id`,`pr`.`Name`,`pr`.`Age` FROM `Person` pr Left JOIN `Employee` em ON ( `em`.`PersonId` = `pr`.`Id` )
第二个方法:
var query = context.Client.Queryable(context.Client.Queryable<Person>(),
context.Client.Queryable<Employee>(),
(pr, em) => pr.Id == em.PersonId);
这个方法使用内连接连接两个表,最后一个参数用来指定两个表之间的连接字段。
生成的SQL类似如下:
SELECT `pr`.`Id` AS `Person.Id` , `pr`.`Name` AS `Person.Name` , `pr`.`Age` AS `Person.Age` , `em`.`Id` AS `Employee.Id` , `em`.`Name` AS `Employee.Name` , `em`.`PersonId` AS `Employee.PersonId` , `em`.`DeptId` AS `Employee.DeptId` FROM (SELECT `Id`,`Name`,`Age` FROM `Person` ) pr Inner JOIN (SELECT `Id`,`Name`,`PersonId`,`DeptId` FROM `Employee` ) em ON ( `pr`.`Id` = `em`.`PersonId` )
第三个方法在第二个方法的基础上,可以指定连接方式:
var query = context.Client.Queryable(context.Client.Queryable<Person>(),
context.Client.Queryable<Employee>(),
JoinType.Left,
(pr, em) => pr.Id == em.PersonId);
最后一个:
var query = context.Client.Queryable<Person, Employee>((pr, em) => pr.Id == em.PersonId);
直接指定两个表之间的联系方式。
需要指出的是,所有的方法都只是返回了一个可查询对象,如果不进行后续的投影(进行select)则可能会提示主键冲突。而且,所有的方法在进行ToXXX之前都不会立即执行。
1.2 查询函数
SqlSugar添加了很多我们常用的方法,使其可以映射为sql语句。我们来看一下支持哪些内容:
public class SqlFunc
{
public static TResult AggregateAvg<TResult>(TResult thisValue);//针对这个列进行取平均数统计
public static int AggregateCount<TResult>(TResult thisValue);// 统计这个列数量 等价于 SQL里的 count(x)
public static int AggregateDistinctCount<TResult>(TResult thisValue);/ 返回去重之后的数量
public static TResult AggregateMax<TResult>(TResult thisValue);//返回最大值
public static TResult AggregateMin<TResult>(TResult thisValue);// 返回最小值
public static TResult AggregateSum<TResult>(TResult thisValue);// 返回总和
public static bool Between(object value, object start, object end);// 判断列的值是否在两个值之间
public static int CharIndex(string findChar, string searchValue);// SQL 的charindex
public static bool Contains(string thisValue, string parameterValue);// 是否包含
public static bool ContainsArray<T>(T[] thisValue, object InField);// 数组是否包含
public static bool ContainsArray<T>(List<T> thisValue, object InField);//列表苏菲包含
public static bool ContainsArrayUseSqlParameters<T>(List<T> thisValue, object InField);//
public static bool ContainsArrayUseSqlParameters<T>(T[] thisValue, object InField);//
public static DateTime DateAdd(DateTime date, int addValue, DateType dataType);// 时间添加
public static DateTime DateAdd(DateTime date, int addValue);// 日期添加
public static bool DateIsSame(DateTime date1, DateTime date2);// 时间是否相同
public static bool DateIsSame(DateTime? date1, DateTime? date2);//时间是否相同
public static bool DateIsSame(DateTime date1, DateTime date2, DateType dataType);//时间是否相同,根据DateType判断
public static int DateValue(DateTime date, DateType dataType);// 根据dateType, 返回具体的时间值
public static bool EndsWith(string thisValue, string parameterValue);//字符串是否以某些值结尾
public static bool Equals(object thisValue, object parameterValue);//是否相等
public static DateTime GetDate();//返回当前数据库时间
public static string GetRandom();//
public static TResult GetSelfAndAutoFill<TResult>(TResult value);//
public static bool HasNumber(object thisValue);//返回是否大于0,且不能为Null
public static bool HasValue(object thisValue);// 是否有值,且不为Null
public static CaseThen IF(bool condition);// sql 里的if判断
public static TResult IIF<TResult>(bool Expression, TResult thenValue, TResult elseValue);// case when
public static TResult IsNull<TResult>(TResult thisValue, TResult ifNullValue);// sql 里的 IsNull
public static bool IsNullOrEmpty(object thisValue);//判断是否是Null或者空
public static int Length(object value);//取长度
public static TResult MappingColumn<TResult>(TResult oldColumnName, string newColumnName);// 列名映射
public static string MergeString(string value1, string value2);
public static string MergeString(string value1, string value2, string value3, string value4);
public static string MergeString(string value1, string value2, string value3, string value4, string value5);
public static string MergeString(string value1, string value2, string value3, string value4, string value5, string value6);
public static string MergeString(string value1, string value2, string value3);
public static string MergeString(string value1, string value2, string value3, string value4, string value5, string value6, string value7);
public static string Replace(object value, string oldChar, string newChar);// 替换
public static bool StartsWith(string thisValue, string parameterValue);
public static Subqueryable<T> Subqueryable<T>() where T : class, new();
public static string Substring(object value, int index, int length);// 获取子串
public static bool ToBool(object value);//类型转换
public static DateTime ToDate(object value);// 类型转换
public static decimal ToDecimal(object value);// 类型转换
public static double ToDouble(object value);// 类型转换
public static Guid ToGuid(object value);// 类型转换
public static int ToInt32(object value);// 类型转换
public static long ToInt64(object value);// 类型转换
public static string ToLower(object thisValue);