FreeSql (二十九)Lambda 表達式

FreeSql 支持功能豐富的表達式函數解析,方便程序員在不瞭解數據庫函數的狀況下編寫代碼。這是 FreeSql 很是特點的功能之一,深刻細化函數解析儘可能作到滿意,所支持的類型基本均可以使用對應的表達式函數,例如 日期、字符串、IN查詢、數組(PostgreSQL的數組)、字典(PostgreSQL HStore)等等。html

IFreeSql fsql = new FreeSql.FreeSqlBuilder()
    .UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=10")
    .Build();

[Table(Name = "tb_topic")]
class Topic {
    [Column(IsIdentity = true, IsPrimary = true)]
    public int Id { get; set; }
    public int Clicks { get; set; }
    public int TestTypeInfoGuid { get; set; }
    public string Title { get; set; }
    public DateTime CreateTime { get; set; }
}

ISelect<Topic> select => fsql.Select<Topic>();

In查詢

var t1 = select.Where(a => new[] { 1, 2, 3 }.Contains(a.testFieldInt)).ToSql();
//SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a.`Title`, a.`CreateTime` 
//FROM `tb_topic` a 
//WHERE (a.`Id` in (1,2,3))

查找今天建立的數據

var t2 = select.Where(a => a.CreateTime.Date == DateTime.Now.Date).ToSql();

SqlServer 下隨機獲取記錄

var t3 = select.OrderBy(a => Guid.NewGuid()).Limit(1).ToSql();
//SELECT top 1 ...
//FROM [tb_topic] a 
//ORDER BY newid()

AOP攔截實現自定義解析

IFreeSql 對象有 Aop 成員,那裏提供一堆 AOP 攔截的方法。其實有一個事件名稱:ParseExpression。程序員

/// <summary>
/// 可自定義解析表達式
/// </summary>
EventHandler<AopParseExpressionEventArgs> ParseExpression { get; set; }

public class AopParseExpressionEventArgs : EventArgs {
    public AopParseExpressionEventArgs(Expression expression, Func<Expression, string> freeParse) {
        this.Expression = expression;
        this.FreeParse = freeParse;
    }

    /// <summary>
    /// 內置解析功能,可輔助您進行解析
    /// </summary>
    public Func<Expression, string> FreeParse { get; }

    /// <summary>
    /// 須要您解析的表達式
    /// </summary>
    public Expression Expression { get; }
    /// <summary>
    /// 解析後的內容
    /// </summary>
    public string Result { get; set; }
}

FreeParse 是提供給外部的解析工具,它擁有 FreeSql 全部表達式功能,當您自定義解析的過程當中遇到特別難處理的,可經過它快速解析出表達式的子部份內容。sql

表達式函數全覽

表達式 MySql SqlServer PostgreSQL Oracle 功能說明
a ? b : c case when a then b else c end case when a then b else c end case when a then b else c end case when a then b else c end a成立時取b值,不然取c值
a ?? b ifnull(a, b) isnull(a, b) coalesce(a, b) nvl(a, b) 當a爲null時,取b值
數字 + 數字 a + b a + b a + b a + b 數字相加
數字 + 字符串 concat(a, b) cast(a as varchar) + cast(b as varchar) case(a as varchar)|| b a|| b 字符串相加,a或b任意一個爲字符串時
a - b a - b a - b a - b a - b
a * b a * b a * b a * b a * b
a / b a / b a / b a / b a / b
a / b a div b a / b a / b trunc(a / b) 整除(a,b都爲整數)
a % b a % b a % b a % b mod(a,b)

等等...數據庫

數組

表達式 MySql SqlServer PostgreSQL Oracle 功能說明
a.Length - - case when a is null then 0 else array_length(a,1) end - 數組長度
常量數組.Length - - array_length(array[常量數組元素逗號分割],1) - 數組長度
a.Any() - - case when a is null then 0 else array_length(a,1) end > 0 - 數組是否爲空
常量數組.Contains(b) b in (常量數組元素逗號分割) b in (常量數組元素逗號分割) b in (常量數組元素逗號分割) b in (常量數組元素逗號分割) IN查詢
a.Contains(b) - - a @> array[b] - a數組是否包含b元素
a.Concat(b) - - a || b - 數組相連
a.Count() - - 同 Length - 數組長度

一個細節證實 FreeSql 匠心製做express

通用的 in 查詢 select.Where(a => new []{ 1,2,3 }.Contains(a.xxx))json

假設 xxxs 是 pgsql 的數組字段類型,其實會與上面的 in 查詢起衝突,FreeSql 解決了這個矛盾 select.Where(a => a.xxxs.Contains(1))數組

字典 Dictionary<string, string>

表達式 MySql SqlServer PostgreSQL Oracle 功能說明
a.Count - - case when a is null then 0 else array_length(akeys(a),1) end - 字典長度
a.Keys - - akeys(a) - 返回字典全部key數組
a.Values - - avals(a) - 返回字典全部value數組
a.Contains(b) - - a @> b - 字典是否包含b
a.ContainsKey(b) - - a? b - 字典是否包含key
a.Concat(b) - - a || b - 字典相連
a.Count() - - 同 Count - 字典長度

JSON JToken/JObject/JArray

表達式 MySql SqlServer PostgreSQL Oracle 功能說明
a.Count - - jsonb_array_length(coalesce(a, '[])) - json數組類型的長度
a.Any() - - jsonb_array_length(coalesce(a, '[])) > 0 - json數組類型,是否爲空
a.Contains(b) - - coalesce(a, '{}') @> b::jsonb - json中是否包含b
a.ContainsKey(b) - - coalesce(a, '{}') ? b - json中是否包含鍵b
a.Concat(b) - - coalesce(a, '{}') b::jsonb
Parse(a) - - a::jsonb - 轉化字符串爲json類型

字符串

表達式 MySql SqlServer PostgreSQL Oracle Sqlite
string.Empty '' '' '' ''
string.IsNullOrEmpty(a) (a is null or a = '') (a is null or a = '') (a is null or a = '') (a is null or a = '') (a is null or a = '')
string.Concat(a,b,c...) concat(a, b, c) a + b + c a || b || c a || b || c a || b || c
a.CompareTo(b) strcmp(a, b) - case when a = b then 0 when a > b then 1 else -1 end case when a = b then 0 when a > b then 1 else -1 end case when a = b then 0 when a > b then 1 else -1 end
a.Contains('b') a like '%b%' a like '%b%' a ilike'%b%' a like '%b%' a like '%b%'
a.EndsWith('b') a like '%b' a like '%b' a ilike'%b' a like '%b' a like '%b'
a.IndexOf(b) locate(a, b) - 1 locate(a, b) - 1 strpos(a, b) - 1 instr(a, b, 1, 1) - 1 instr(a, b) - 1
a.Length char_length(a) len(a) char_length(a) length(a) length(a)
a.PadLeft(b, c) lpad(a, b, c) - lpad(a, b, c) lpad(a, b, c) lpad(a, b, c)
a.PadRight(b, c) rpad(a, b, c) - rpad(a, b, c) rpad(a, b, c) rpad(a, b, c)
a.Replace(b, c) replace(a, b, c) replace(a, b, c) replace(a, b, c) replace(a, b, c) replace(a, b, c)
a.StartsWith('b') a like 'b%' a like 'b%' a ilike'b%' a like 'b%' a like 'b%'
a.Substring(b, c) substr(a, b, c + 1) substring(a, b, c + 1) substr(a, b, c + 1) substr(a, b, c + 1) substr(a, b, c + 1)
a.ToLower lower(a) lower(a) lower(a) lower(a) lower(a)
a.ToUpper upper(a) upper(a) upper(a) upper(a) upper(a)
a.Trim trim(a) trim(a) trim(a) trim(a) trim(a)
a.TrimEnd rtrim(a) rtrim(a) rtrim(a) rtrim(a) rtrim(a)
a.TrimStart ltrim(a) ltrim(a) ltrim(a) ltrim(a) ltrim(a)

使用字符串函數可能會出現性能瓶頸,雖然不推薦使用,可是做爲功能庫這也是不可缺乏的功能之一。dom

日期

表達式 MySql SqlServer PostgreSQL Oracle
DateTime.Now now() getdate() current_timestamp systimestamp
DateTime.UtcNow utc_timestamp() getutcdate() (current_timestamp at time zone 'UTC') sys_extract_utc(systimestamp)
DateTime.Today curdate convert(char(10),getdate(),120) current_date trunc(systimestamp)
DateTime.MaxValue cast('9999/12/31 23:59:59' as datetime) '9999/12/31 23:59:59' '9999/12/31 23:59:59'::timestamp to_timestamp('9999-12-31 23:59:59','YYYY-MM-DD HH24:MI:SS.FF6')
DateTime.MinValue cast('0001/1/1 0:00:00' as datetime) '1753/1/1 0:00:00' '0001/1/1 0:00:00'::timestamp to_timestamp('0001-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS.FF6')
DateTime.Compare(a, b) a - b a - b extract(epoch from a::timestamp-b::timestamp) extract(day from (a-b))
DateTime.DaysInMonth(a, b) dayofmonth(last_day(concat(a, '-', b, '-1'))) datepart(day, dateadd(day, -1, dateadd(month, 1, cast(a as varchar) + '-' + cast(b as varchar) + '-1'))) extract(day from (a
DateTime.Equals(a, b) a = b a = b a = b a = b
DateTime.IsLeapYear(a) a%4=0 and a%100<>0 or a%400=0 a%4=0 and a%100<>0 or a%400=0 a%4=0 and a%100<>0 or a%400=0 mod(a,4)=0 AND mod(a,100)<>0 OR mod(a,400)=0
DateTime.Parse(a) cast(a as datetime) cast(a as datetime) a::timestamp to_timestamp(a,'YYYY-MM-DD HH24:MI:SS.FF6')
a.Add(b) date_add(a, interval b microsecond) dateadd(millisecond, b / 1000, a) a::timestamp+(b
a.AddDays(b) date_add(a, interval b day) dateadd(day, b, a) a::timestamp+(b
a.AddHours(b) date_add(a, interval b hour) dateadd(hour, b, a) a::timestamp+(b
a.AddMilliseconds(b) date_add(a, interval b*1000 microsecond) dateadd(millisecond, b, a) a::timestamp+(b
a.AddMinutes(b) date_add(a, interval b minute) dateadd(minute, b, a) a::timestamp+(b
a.AddMonths(b) date_add(a, interval b month) dateadd(month, b, a) a::timestamp+(b
a.AddSeconds(b) date_add(a, interval b second) dateadd(second, b, a) a::timestamp+(b
a.AddTicks(b) date_add(a, interval b/10 microsecond) dateadd(millisecond, b / 10000, a) a::timestamp+(b
a.AddYears(b) date_add(a, interval b year) dateadd(year, b, a) a::timestamp+(b
a.Date cast(date_format(a, '%Y-%m-%d') as datetime) convert(char(10),a,120) a::date trunc(a)
a.Day dayofmonth(a) datepart(day, a) extract(day from a::timestamp) cast(to_char(a,'DD') as number)
a.DayOfWeek dayofweek(a) datepart(weekday, a) - 1 extract(dow from a::timestamp) case when to_char(a)='7' then 0 else cast(to_char(a) as number) end
a.DayOfYear dayofyear(a) datepart(dayofyear, a) extract(doy from a::timestamp) cast(to_char(a,'DDD') as number)
a.Hour hour(a) datepart(hour, a) extract(hour from a::timestamp) cast(to_char(a,'HH24') as number)
a.Millisecond floor(microsecond(a) / 1000) datepart(millisecond, a) extract(milliseconds from a::timestamp)-extract(second from a::timestamp)*1000 cast(to_char(a,'FF3') as number)
a.Minute minute(a) datepart(minute, a) extract(minute from a::timestamp) cast(to_char(a,'MI') as number)
a.Month month(a) datepart(month, a) extract(month from a::timestamp) cast(to_char(a,'FF3') as number)
a.Second second(a) datepart(second, a) extract(second from a::timestamp) cast(to_char(a,'SS') as number)
a.Subtract(b) timestampdiff(microsecond, b, a) datediff(millisecond, b, a) * 1000 (extract(epoch from a::timestamp-b::timestamp)*1000000) a - b
a.Ticks timestampdiff(microsecond, '0001-1-1', a) * 10 datediff(millisecond, '1970-1-1', a) * 10000 + 621355968000000000 extract(epoch from a::timestamp)*10000000+621355968000000000 cast(to_char(a,'FF7') as number)
a.TimeOfDay timestampdiff(microsecond, date_format(a, '%Y-%m-%d'), a) '1970-1-1 ' + convert(varchar, a, 14) extract(epoch from a::time)*1000000 a - trunc(a)
a.Year year(a) datepart(year, a) extract(year from a::timestamp)
a.Equals(b) a = b a = b a = b a = b
a.CompareTo(b) a - b a - b a - b a - b
a.ToString() date_format(a, '%Y-%m-%d %H:%i:%s.%f') convert(varchar, a, 121) to_char(a, 'YYYY-MM-DD HH24:MI:SS.US') to_char(a,'YYYY-MM-DD HH24:MI:SS.FF6')

時間

表達式 MySql(微秒) SqlServer(秒) PostgreSQL(微秒) Oracle(Interval day(9) to second(7))
TimeSpan.Zero 0 0 - 0微秒
TimeSpan.MaxValue 922337203685477580 922337203685477580 - numtodsinterval(233720368.5477580,'second')
TimeSpan.MinValue -922337203685477580 -922337203685477580 - numtodsinterval(-233720368.5477580,'second')
TimeSpan.Compare(a, b) a - b a - b - extract(day from (a-b))
TimeSpan.Equals(a, b) a = b a = b - a = b
TimeSpan.FromDays(a) a * 1000000 * 60 * 60 * 24 a * 1000000 * 60 * 60 * 24 - numtodsinterval(a*86400,'second')
TimeSpan.FromHours(a) a * 1000000 * 60 * 60 a * 1000000 * 60 * 60 - numtodsinterval(a*3600,'second')
TimeSpan.FromMilliseconds(a) a * 1000 a * 1000 - numtodsinterval(a/1000,'second')
TimeSpan.FromMinutes(a) a * 1000000 * 60 a * 1000000 * 60 - numtodsinterval(a*60,'second')
TimeSpan.FromSeconds(a) a * 1000000 a * 1000000 - numtodsinterval(a,'second')
TimeSpan.FromTicks(a) a / 10 a / 10 - numtodsinterval(a/10000000,'second')
a.Add(b) a + b a + b - a + b
a.Subtract(b) a - b a - b - a - b
a.CompareTo(b) a - b a - b - extract(day from (a-b))
a.Days a div (1000000 * 60 * 60 * 24) a div (1000000 * 60 * 60 * 24) - extract(day from a)
a.Hours a div (1000000 * 60 * 60) mod 24 a div (1000000 * 60 * 60) mod 24 - extract(hour from a)
a.Milliseconds a div 1000 mod 1000 a div 1000 mod 1000 - cast(substr(extract(second from a)-floor(extract(second from a)),2,3) as number)
a.Seconds a div 1000000 mod 60 a div 1000000 mod 60 - extract(second from a)
a.Ticks a * 10 a * 10 - (extract(day from a)86400+extract(hour from a)3600+extract(minute from a)60+extract(second from a))10000000
a.TotalDays a / (1000000 * 60 * 60 * 24) a / (1000000 * 60 * 60 * 24) - extract(day from a)
a.TotalHours a / (1000000 * 60 * 60) a / (1000000 * 60 * 60) - (extract(day from a)*24+extract(hour from a))
a.TotalMilliseconds a / 1000 a / 1000 - (extract(day from a)86400+extract(hour from a)3600+extract(minute from a)60+extract(second from a))1000
a.TotalMinutes a / (1000000 * 60) a / (1000000 * 60) -
a.TotalSeconds a / 1000000 a / 1000000 - (extract(day from a)86400+extract(hour from a)3600+extract(minute from a)*60+extract(second from a))
a.Equals(b) a = b a = b - a = b
a.ToString() cast(a as varchar) cast(a as varchar) - to_char(a)

數學函數

表達式 MySql SqlServer PostgreSQL Oracle
Math.Abs(a) abs(a) abs(a) abs(a)
Math.Acos(a) acos(a) acos(a) acos(a) acos(a)
Math.Asin(a) asin(a) asin(a) asin(a) asin(a)
Math.Atan(a) atan(a) atan(a) atan(a) atan(a)
Math.Atan2(a, b) atan2(a, b) atan2(a, b) atan2(a, b) -
Math.Ceiling(a) ceiling(a) ceiling(a) ceiling(a) ceil(a)
Math.Cos(a) cos(a) cos(a) cos(a) cos(a)
Math.Exp(a) exp(a) exp(a) exp(a) exp(a)
Math.Floor(a) floor(a) floor(a) floor(a) floor(a)
Math.Log(a) log(a) log(a) log(a) log(e,a)
Math.Log10(a) log10(a) log10(a) log10(a) log(10,a)
Math.PI(a) 3.1415926535897931 3.1415926535897931 3.1415926535897931 3.1415926535897931
Math.Pow(a, b) pow(a, b) power(a, b) pow(a, b) power(a, b)
Math.Round(a, b) round(a, b) round(a, b) round(a, b) round(a, b)
Math.Sign(a) sign(a) sign(a) sign(a) sign(a)
Math.Sin(a) sin(a) sin(a) sin(a) sin(a)
Math.Sqrt(a) sqrt(a) sqrt(a) sqrt(a) sqrt(a)
Math.Tan(a) tan(a) tan(a) tan(a) tan(a)
Math.Truncate(a) truncate(a, 0) floor(a) trunc(a, 0) trunc(a, 0)

類型轉換

表達式 MySql SqlServer PostgreSQL Oracle Sqlite
Convert.ToBoolean(a) | bool.Parse(a) a not in ('0','false') a not in ('0','false') a::varchar not in ('0','false','f','no') - a not in ('0','false')
Convert.ToByte(a) | byte.Parse(a) cast(a as unsigned) cast(a as tinyint) a::int2 cast(a as number) cast(a as int2)
Convert.ToChar(a) substr(cast(a as char),1,1) substring(cast(a as nvarchar),1,1) substr(a::char,1,1) substr(to_char(a),1,1) substr(cast(a as character),1,1)
Convert.ToDateTime(a) | DateTime.Parse(a) cast(a as datetime) cast(a as datetime) a::timestamp to_timestamp(a,'YYYY-MM-DD HH24:MI:SS.FF6') datetime(a)
Convert.ToDecimal(a) | decimal.Parse(a) cast(a as decimal(36,18)) cast(a as decimal(36,19)) a::numeric cast(a as number) cast(a as decimal(36,18))
Convert.ToDouble(a) | double.Parse(a) cast(a as decimal(32,16)) cast(a as decimal(32,16)) a::float8 cast(a as number) cast(a as double)
Convert.ToInt16(a) | short.Parse(a) cast(a as signed) cast(a as smallint) a::int2 cast(a as number) cast(a as smallint)
Convert.ToInt32(a) | int.Parse(a) cast(a as signed) cast(a as int) a::int4 cast(a as number) cast(a as smallint)
Convert.ToInt64(a) | long.Parse(a) cast(a as signed) cast(a as bigint) a::int8 cast(a as number) cast(a as smallint)
Convert.ToSByte(a) | sbyte.Parse(a) cast(a as signed) cast(a as tinyint) a::int2 cast(a as number) cast(a as smallint)
Convert.ToString(a) cast(a as decimal(14,7)) cast(a as decimal(14,7)) a::float4 to_char(a) cast(a as character)
Convert.ToSingle(a) | float.Parse(a) cast(a as char) cast(a as nvarchar) a::varchar cast(a as number) cast(a as smallint)
Convert.ToUInt16(a) | ushort.Parse(a) cast(a as unsigned) cast(a as smallint) a::int2 cast(a as number) cast(a as unsigned)
Convert.ToUInt32(a) | uint.Parse(a) cast(a as unsigned) cast(a as int) a::int4 cast(a as number) cast(a as decimal(10,0))
Convert.ToUInt64(a) | ulong.Parse(a) cast(a as unsigned) cast(a as bigint) a::int8 cast(a as number) cast(a as decimal(21,0))
Guid.Parse(a) substr(cast(a as char),1,36) cast(a as uniqueidentifier) a::uuid substr(to_char(a),1,36) substr(cast(a as character),1,36)
Guid.NewGuid() - newid() - - -
new Random().NextDouble() rand() rand() random() dbms_random.value random()

系列文章導航

相關文章
相關標籤/搜索