diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index 1a43f59e..9c0597d5 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -106,13 +106,6 @@ 清空状态数据 - - - 根据 lambda 条件删除数据 - - - - 添加 diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerExpression/OtherTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerExpression/OtherTest.cs index 97562143..459fc7bf 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerExpression/OtherTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerExpression/OtherTest.cs @@ -105,9 +105,65 @@ namespace FreeSql.Tests.SqlServerExpression var sql111111 = select.Where(a => inarray.Contains(a.testFieldInt)).ToList(); var sql112222 = select.Where(a => inarray.Contains(a.testFieldInt) == false).ToList(); var sql113333 = select.Where(a => !inarray.Contains(a.testFieldInt)).ToList(); + + //nvarchar + IEnumerable stringlinqlist = new List(new[] { "a1", "a2", "a3" }); + var ntestlinq = select.Where(a => stringlinqlist.Contains(a.testFieldString)).ToList(); + + //in not in + var nsql111 = select.Where(a => new[] { "a1", "a2", "a3" }.Contains(a.testFieldString)).ToList(); + var nsql112 = select.Where(a => new[] { "a1", "a2", "a3" }.Contains(a.testFieldString) == false).ToList(); + var nsql113 = select.Where(a => !new[] { "a1", "a2", "a3" }.Contains(a.testFieldString)).ToList(); + + var ninarray = new[] { "a1", "a2", "a3" }; + var nsql1111 = select.Where(a => ninarray.Contains(a.testFieldString)).ToList(); + var nsql1122 = select.Where(a => ninarray.Contains(a.testFieldString) == false).ToList(); + var nsql1133 = select.Where(a => !ninarray.Contains(a.testFieldString)).ToList(); + + //in not in + var nsql11111 = select.Where(a => new List() { "a1", "a2", "a3" }.Contains(a.testFieldString)).ToList(); + var nsql11222 = select.Where(a => new List() { "a1", "a2", "a3" }.Contains(a.testFieldString) == false).ToList(); + var nsql11333 = select.Where(a => !new List() { "a1", "a2", "a3" }.Contains(a.testFieldString)).ToList(); + + var nsql11111a = select.Where(a => new List(new[] { "a1", "a2", "a3" }).Contains(a.testFieldString)).ToList(); + var nsql11222b = select.Where(a => new List(new[] { "a1", "a2", "a3" }).Contains(a.testFieldString) == false).ToList(); + var nsql11333c = select.Where(a => !new List(new[] { "a1", "a2", "a3" }).Contains(a.testFieldString)).ToList(); + + var ninarray2 = new List() { "a1", "a2", "a3" }; + var nsql111111 = select.Where(a => ninarray2.Contains(a.testFieldString)).ToList(); + var nsql112222 = select.Where(a => ninarray2.Contains(a.testFieldString) == false).ToList(); + var nsql113333 = select.Where(a => !ninarray2.Contains(a.testFieldString)).ToList(); + + //varchar + IEnumerable vstringlinqlist = new List(new[] { "a1", "a2", "a3" }); + var vtestlinq = select.Where(a => vstringlinqlist.Contains(a.testFieldStringVarchar)).ToList(); + + //in not in + var vsql111 = select.Where(a => new[] { "a1", "a2", "a3" }.Contains(a.testFieldStringVarchar)).ToList(); + var vsql112 = select.Where(a => new[] { "a1", "a2", "a3" }.Contains(a.testFieldStringVarchar) == false).ToList(); + var vsql113 = select.Where(a => !new[] { "a1", "a2", "a3" }.Contains(a.testFieldStringVarchar)).ToList(); + + var vinarray = new[] { "a1", "a2", "a3" }; + var vsql1111 = select.Where(a => ninarray.Contains(a.testFieldStringVarchar)).ToList(); + var vsql1122 = select.Where(a => ninarray.Contains(a.testFieldStringVarchar) == false).ToList(); + var vsql1133 = select.Where(a => !ninarray.Contains(a.testFieldStringVarchar)).ToList(); + + //in not in + var vsql11111 = select.Where(a => new List() { "a1", "a2", "a3" }.Contains(a.testFieldStringVarchar)).ToList(); + var vsql11222 = select.Where(a => new List() { "a1", "a2", "a3" }.Contains(a.testFieldStringVarchar) == false).ToList(); + var vsql11333 = select.Where(a => !new List() { "a1", "a2", "a3" }.Contains(a.testFieldStringVarchar)).ToList(); + + var vsql11111a = select.Where(a => new List(new[] { "a1", "a2", "a3" }).Contains(a.testFieldStringVarchar)).ToList(); + var vsql11222b = select.Where(a => new List(new[] { "a1", "a2", "a3" }).Contains(a.testFieldStringVarchar) == false).ToList(); + var vsql11333c = select.Where(a => !new List(new[] { "a1", "a2", "a3" }).Contains(a.testFieldStringVarchar)).ToList(); + + var vinarray2 = new List() { "a1", "a2", "a3" }; + var vsql111111 = select.Where(a => ninarray2.Contains(a.testFieldStringVarchar)).ToList(); + var vsql112222 = select.Where(a => ninarray2.Contains(a.testFieldStringVarchar) == false).ToList(); + var vsql113333 = select.Where(a => !ninarray2.Contains(a.testFieldStringVarchar)).ToList(); } - [Table(Name = "tb_alltype")] + [Table(Name = "tb_alltypeOther")] class TableAllType { [Column(IsIdentity = true, IsPrimary = true)] @@ -131,6 +187,9 @@ namespace FreeSql.Tests.SqlServerExpression public DateTimeOffset testFieldDateTimeOffset { get; set; } public byte[] testFieldBytes { get; set; } public string testFieldString { get; set; } + + [Column(DbType = "varchar(255)")] + public string testFieldStringVarchar { get; set; } public Guid testFieldGuid { get; set; } public bool? testFieldBoolNullable { get; set; } diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerExpression/StringTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerExpression/StringTest.cs index c0272fa8..ecdadd3b 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerExpression/StringTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/SqlServerExpression/StringTest.cs @@ -29,6 +29,8 @@ namespace FreeSql.Tests.SqlServerExpression public int TypeGuid { get; set; } public TestTypeInfo Type { get; set; } public string Title { get; set; } + [Column(DbType = "varchar(255)")] + public string TitleVarchar { get; set; } public DateTime CreateTime { get; set; } } class TestTypeInfo @@ -56,7 +58,11 @@ namespace FreeSql.Tests.SqlServerExpression { var list = new List(); list.Add(select.Where(a => a.Title.Equals("aaa")).ToList()); + list.Add(select.Where(a => a.TitleVarchar.Equals("aaa")).ToList()); list.Add(g.sqlserver.Select().Where(a => a.id.Equals(Guid.Empty)).ToList()); + + list.Add(select.Where(a => a.Title == "aaa").ToList()); + list.Add(select.Where(a => a.TitleVarchar == "aaa").ToList()); } [Fact] @@ -64,6 +70,7 @@ namespace FreeSql.Tests.SqlServerExpression { var data = new List(); data.Add(select.Where(a => (a.Title ?? "") == string.Empty).ToSql()); + data.Add(select.Where(a => (a.TitleVarchar ?? "") == string.Empty).ToSql()); } [Fact] @@ -79,6 +86,16 @@ namespace FreeSql.Tests.SqlServerExpression list.Add(select.Where(a => (a.Title + "aaa").StartsWith(a.Title)).ToList()); list.Add(select.Where(a => (a.Title + "aaa").StartsWith(a.Title + 1)).ToList()); list.Add(select.Where(a => (a.Title + "aaa").StartsWith(a.Type.Name)).ToList()); + + list.Add(select.Where(a => a.TitleVarchar.StartsWith("aaa")).ToList()); + list.Add(select.Where(a => a.TitleVarchar.StartsWith(a.TitleVarchar)).ToList()); + list.Add(select.Where(a => a.TitleVarchar.StartsWith(a.TitleVarchar + 1)).ToList()); + list.Add(select.Where(a => a.TitleVarchar.StartsWith(a.Type.Name)).ToList()); + + list.Add(select.Where(a => (a.TitleVarchar + "aaa").StartsWith("aaa")).ToList()); + list.Add(select.Where(a => (a.TitleVarchar + "aaa").StartsWith(a.TitleVarchar)).ToList()); + list.Add(select.Where(a => (a.TitleVarchar + "aaa").StartsWith(a.TitleVarchar + 1)).ToList()); + list.Add(select.Where(a => (a.TitleVarchar + "aaa").StartsWith(a.Type.Name)).ToList()); } [Fact] public void EndsWith() @@ -93,6 +110,16 @@ namespace FreeSql.Tests.SqlServerExpression list.Add(select.Where(a => (a.Title + "aaa").EndsWith(a.Title)).ToList()); list.Add(select.Where(a => (a.Title + "aaa").EndsWith(a.Title + 1)).ToList()); list.Add(select.Where(a => (a.Title + "aaa").EndsWith(a.Type.Name)).ToList()); + + list.Add(select.Where(a => a.TitleVarchar.EndsWith("aaa")).ToList()); + list.Add(select.Where(a => a.TitleVarchar.EndsWith(a.TitleVarchar)).ToList()); + list.Add(select.Where(a => a.TitleVarchar.EndsWith(a.TitleVarchar + 1)).ToList()); + list.Add(select.Where(a => a.TitleVarchar.EndsWith(a.Type.Name)).ToList()); + + list.Add(select.Where(a => (a.TitleVarchar + "aaa").EndsWith("aaa")).ToList()); + list.Add(select.Where(a => (a.TitleVarchar + "aaa").EndsWith(a.TitleVarchar)).ToList()); + list.Add(select.Where(a => (a.TitleVarchar + "aaa").EndsWith(a.TitleVarchar + 1)).ToList()); + list.Add(select.Where(a => (a.TitleVarchar + "aaa").EndsWith(a.Type.Name)).ToList()); } [Fact] public void Contains() @@ -107,6 +134,16 @@ namespace FreeSql.Tests.SqlServerExpression list.Add(select.Where(a => (a.Title + "aaa").Contains(a.Title)).ToList()); list.Add(select.Where(a => (a.Title + "aaa").Contains(a.Title + 1)).ToList()); list.Add(select.Where(a => (a.Title + "aaa").Contains(a.Type.Name)).ToList()); + + list.Add(select.Where(a => a.TitleVarchar.Contains("aaa")).ToList()); + list.Add(select.Where(a => a.TitleVarchar.Contains(a.TitleVarchar)).ToList()); + list.Add(select.Where(a => a.TitleVarchar.Contains(a.TitleVarchar + 1)).ToList()); + list.Add(select.Where(a => a.TitleVarchar.Contains(a.Type.Name)).ToList()); + + list.Add(select.Where(a => (a.TitleVarchar + "aaa").Contains("aaa")).ToList()); + list.Add(select.Where(a => (a.TitleVarchar + "aaa").Contains(a.TitleVarchar)).ToList()); + list.Add(select.Where(a => (a.TitleVarchar + "aaa").Contains(a.TitleVarchar + 1)).ToList()); + list.Add(select.Where(a => (a.TitleVarchar + "aaa").Contains(a.Type.Name)).ToList()); } [Fact] public void ToLower() @@ -121,6 +158,16 @@ namespace FreeSql.Tests.SqlServerExpression data.Add(select.Where(a => (a.Title.ToLower() + "aaa").ToLower() == a.Title).ToList()); data.Add(select.Where(a => (a.Title.ToLower() + "aaa").ToLower() == (a.Title + 1)).ToList()); data.Add(select.Where(a => (a.Title.ToLower() + "aaa").ToLower() == a.Type.Name).ToList()); + + data.Add(select.Where(a => a.TitleVarchar.ToLower() == "aaa").ToList()); + data.Add(select.Where(a => a.TitleVarchar.ToLower() == a.TitleVarchar).ToList()); + data.Add(select.Where(a => a.TitleVarchar.ToLower() == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => a.TitleVarchar.ToLower() == a.Type.Name).ToList()); + + data.Add(select.Where(a => (a.TitleVarchar.ToLower() + "aaa").ToLower() == "aaa").ToList()); + data.Add(select.Where(a => (a.TitleVarchar.ToLower() + "aaa").ToLower() == a.TitleVarchar).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.ToLower() + "aaa").ToLower() == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.ToLower() + "aaa").ToLower() == a.Type.Name).ToList()); } [Fact] public void ToUpper() @@ -135,6 +182,16 @@ namespace FreeSql.Tests.SqlServerExpression data.Add(select.Where(a => (a.Title.ToUpper() + "aaa").ToUpper() == a.Title).ToList()); data.Add(select.Where(a => (a.Title.ToUpper() + "aaa").ToUpper() == (a.Title + 1)).ToList()); data.Add(select.Where(a => (a.Title.ToUpper() + "aaa").ToUpper() == a.Type.Name).ToList()); + + data.Add(select.Where(a => a.TitleVarchar.ToUpper() == "aaa").ToList()); + data.Add(select.Where(a => a.TitleVarchar.ToUpper() == a.TitleVarchar).ToList()); + data.Add(select.Where(a => a.TitleVarchar.ToUpper() == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => a.TitleVarchar.ToUpper() == a.Type.Name).ToList()); + + data.Add(select.Where(a => (a.TitleVarchar.ToUpper() + "aaa").ToUpper() == "aaa").ToList()); + data.Add(select.Where(a => (a.TitleVarchar.ToUpper() + "aaa").ToUpper() == a.TitleVarchar).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.ToUpper() + "aaa").ToUpper() == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.ToUpper() + "aaa").ToUpper() == a.Type.Name).ToList()); } [Fact] public void Substring() @@ -149,6 +206,16 @@ namespace FreeSql.Tests.SqlServerExpression data.Add(select.Where(a => (a.Title.Substring(0) + "aaa").Substring(0, a.Title.Length) == a.Title).ToList()); data.Add(select.Where(a => (a.Title.Substring(0) + "aaa").Substring(0, 3) == (a.Title + 1)).ToList()); data.Add(select.Where(a => (a.Title.Substring(0) + "aaa").Substring(1, 2) == a.Type.Name).ToList()); + + data.Add(select.Where(a => a.TitleVarchar.Substring(0) == "aaa").ToList()); + data.Add(select.Where(a => a.TitleVarchar.Substring(0) == a.TitleVarchar).ToList()); + data.Add(select.Where(a => a.TitleVarchar.Substring(0) == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => a.TitleVarchar.Substring(0) == a.Type.Name).ToList()); + + data.Add(select.Where(a => (a.TitleVarchar.Substring(0) + "aaa").Substring(a.TitleVarchar.Length) == "aaa").ToList()); + data.Add(select.Where(a => (a.TitleVarchar.Substring(0) + "aaa").Substring(0, a.TitleVarchar.Length) == a.TitleVarchar).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.Substring(0) + "aaa").Substring(0, 3) == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.Substring(0) + "aaa").Substring(1, 2) == a.Type.Name).ToList()); } [Fact] public void Length() @@ -163,6 +230,16 @@ namespace FreeSql.Tests.SqlServerExpression data.Add(select.Where(a => (a.Title + "aaa").Length == 1).ToList()); data.Add(select.Where(a => (a.Title + "aaa").Length == a.Title.Length + 1).ToList()); data.Add(select.Where(a => (a.Title + "aaa").Length == a.Type.Name.Length).ToList()); + + data.Add(select.Where(a => a.TitleVarchar.Length == 0).ToList()); + data.Add(select.Where(a => a.TitleVarchar.Length == 1).ToList()); + data.Add(select.Where(a => a.TitleVarchar.Length == a.TitleVarchar.Length + 1).ToList()); + data.Add(select.Where(a => a.TitleVarchar.Length == a.Type.Name.Length).ToList()); + + data.Add(select.Where(a => (a.TitleVarchar + "aaa").Length == 0).ToList()); + data.Add(select.Where(a => (a.TitleVarchar + "aaa").Length == 1).ToList()); + data.Add(select.Where(a => (a.TitleVarchar + "aaa").Length == a.TitleVarchar.Length + 1).ToList()); + data.Add(select.Where(a => (a.TitleVarchar + "aaa").Length == a.Type.Name.Length).ToList()); } [Fact] public void IndexOf() @@ -177,6 +254,16 @@ namespace FreeSql.Tests.SqlServerExpression data.Add(select.Where(a => (a.Title + "aaa").IndexOf("aaa", 2) == -1).ToList()); data.Add(select.Where(a => (a.Title + "aaa").IndexOf("aaa", 2) == (a.Title.Length + 1)).ToList()); data.Add(select.Where(a => (a.Title + "aaa").IndexOf("aaa", 2) == a.Type.Name.Length + 1).ToList()); + + data.Add(select.Where(a => a.TitleVarchar.IndexOf("aaa") == -1).ToList()); + data.Add(select.Where(a => a.TitleVarchar.IndexOf("aaa", 2) == -1).ToList()); + data.Add(select.Where(a => a.TitleVarchar.IndexOf("aaa", 2) == (a.TitleVarchar.Length + 1)).ToList()); + data.Add(select.Where(a => a.TitleVarchar.IndexOf("aaa", 2) == a.Type.Name.Length + 1).ToList()); + + data.Add(select.Where(a => (a.TitleVarchar + "aaa").IndexOf("aaa") == -1).ToList()); + data.Add(select.Where(a => (a.TitleVarchar + "aaa").IndexOf("aaa", 2) == -1).ToList()); + data.Add(select.Where(a => (a.TitleVarchar + "aaa").IndexOf("aaa", 2) == (a.TitleVarchar.Length + 1)).ToList()); + data.Add(select.Where(a => (a.TitleVarchar + "aaa").IndexOf("aaa", 2) == a.Type.Name.Length + 1).ToList()); } [Fact] public void PadLeft() @@ -219,6 +306,16 @@ namespace FreeSql.Tests.SqlServerExpression data.Add(select.Where(a => (a.Title.Trim('a') + "aaa").Trim('a') == a.Title).ToList()); data.Add(select.Where(a => (a.Title.Trim('a', 'b') + "aaa").Trim('a', 'b') == (a.Title + 1)).ToList()); data.Add(select.Where(a => (a.Title.Trim('a', 'b', 'c') + "aaa").Trim('a', 'b', 'c') == a.Type.Name).ToList()); + + data.Add(select.Where(a => a.TitleVarchar.Trim() == "aaa").ToList()); + data.Add(select.Where(a => a.TitleVarchar.Trim('a') == a.TitleVarchar).ToList()); + data.Add(select.Where(a => a.TitleVarchar.Trim('a', 'b') == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => a.TitleVarchar.Trim('a', 'b', 'c') == a.Type.Name).ToList()); + + data.Add(select.Where(a => (a.TitleVarchar.Trim() + "aaa").Trim() == "aaa").ToList()); + data.Add(select.Where(a => (a.TitleVarchar.Trim('a') + "aaa").Trim('a') == a.TitleVarchar).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.Trim('a', 'b') + "aaa").Trim('a', 'b') == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.Trim('a', 'b', 'c') + "aaa").Trim('a', 'b', 'c') == a.Type.Name).ToList()); } [Fact] public void TrimStart() @@ -233,6 +330,16 @@ namespace FreeSql.Tests.SqlServerExpression data.Add(select.Where(a => (a.Title.TrimStart('a') + "aaa").TrimStart('a') == a.Title).ToList()); data.Add(select.Where(a => (a.Title.TrimStart('a', 'b') + "aaa").TrimStart('a', 'b') == (a.Title + 1)).ToList()); data.Add(select.Where(a => (a.Title.TrimStart('a', 'b', 'c') + "aaa").TrimStart('a', 'b', 'c') == a.Type.Name).ToList()); + + data.Add(select.Where(a => a.TitleVarchar.TrimStart() == "aaa").ToList()); + data.Add(select.Where(a => a.TitleVarchar.TrimStart('a') == a.TitleVarchar).ToList()); + data.Add(select.Where(a => a.TitleVarchar.TrimStart('a', 'b') == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => a.TitleVarchar.TrimStart('a', 'b', 'c') == a.Type.Name).ToList()); + + data.Add(select.Where(a => (a.TitleVarchar.TrimStart() + "aaa").TrimStart() == "aaa").ToList()); + data.Add(select.Where(a => (a.TitleVarchar.TrimStart('a') + "aaa").TrimStart('a') == a.TitleVarchar).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.TrimStart('a', 'b') + "aaa").TrimStart('a', 'b') == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.TrimStart('a', 'b', 'c') + "aaa").TrimStart('a', 'b', 'c') == a.Type.Name).ToList()); } [Fact] public void TrimEnd() @@ -247,6 +354,16 @@ namespace FreeSql.Tests.SqlServerExpression data.Add(select.Where(a => (a.Title.TrimEnd('a') + "aaa").TrimEnd('a') == a.Title).ToList()); data.Add(select.Where(a => (a.Title.TrimEnd('a', 'b') + "aaa").TrimEnd('a', 'b') == (a.Title + 1)).ToList()); data.Add(select.Where(a => (a.Title.TrimEnd('a', 'b', 'c') + "aaa").TrimEnd('a', 'b', 'c') == a.Type.Name).ToList()); + + data.Add(select.Where(a => a.TitleVarchar.TrimEnd() == "aaa").ToList()); + data.Add(select.Where(a => a.TitleVarchar.TrimEnd('a') == a.TitleVarchar).ToList()); + data.Add(select.Where(a => a.TitleVarchar.TrimEnd('a', 'b') == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => a.TitleVarchar.TrimEnd('a', 'b', 'c') == a.Type.Name).ToList()); + + data.Add(select.Where(a => (a.TitleVarchar.TrimEnd() + "aaa").TrimEnd() == "aaa").ToList()); + data.Add(select.Where(a => (a.TitleVarchar.TrimEnd('a') + "aaa").TrimEnd('a') == a.TitleVarchar).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.TrimEnd('a', 'b') + "aaa").TrimEnd('a', 'b') == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.TrimEnd('a', 'b', 'c') + "aaa").TrimEnd('a', 'b', 'c') == a.Type.Name).ToList()); } [Fact] public void Replace() @@ -261,6 +378,16 @@ namespace FreeSql.Tests.SqlServerExpression data.Add(select.Where(a => (a.Title.Replace("a", "b").Replace("b", "c") + "aaa").TrimEnd('a') == a.Title).ToList()); data.Add(select.Where(a => (a.Title.Replace("a", "b").Replace("b", "c").Replace("c", "a") + "aaa").TrimEnd('a', 'b') == (a.Title + 1)).ToList()); data.Add(select.Where(a => (a.Title.Replace("a", "b").Replace("b", "c").Replace(a.Type.Name, "a") + "aaa").TrimEnd('a', 'b', 'c') == a.Type.Name).ToList()); + + data.Add(select.Where(a => a.TitleVarchar.Replace("a", "b") == "aaa").ToList()); + data.Add(select.Where(a => a.TitleVarchar.Replace("a", "b").Replace("b", "c") == a.TitleVarchar).ToList()); + data.Add(select.Where(a => a.TitleVarchar.Replace("a", "b").Replace("b", "c").Replace("c", "a") == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => a.TitleVarchar.Replace("a", "b").Replace("b", "c").Replace(a.Type.Name, "a") == a.Type.Name).ToList()); + + data.Add(select.Where(a => (a.TitleVarchar.Replace("a", "b") + "aaa").TrimEnd() == "aaa").ToList()); + data.Add(select.Where(a => (a.TitleVarchar.Replace("a", "b").Replace("b", "c") + "aaa").TrimEnd('a') == a.TitleVarchar).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.Replace("a", "b").Replace("b", "c").Replace("c", "a") + "aaa").TrimEnd('a', 'b') == (a.TitleVarchar + 1)).ToList()); + data.Add(select.Where(a => (a.TitleVarchar.Replace("a", "b").Replace("b", "c").Replace(a.Type.Name, "a") + "aaa").TrimEnd('a', 'b', 'c') == a.Type.Name).ToList()); } [Fact] public void CompareTo() @@ -284,6 +411,10 @@ namespace FreeSql.Tests.SqlServerExpression data.Add(select.Where(a => string.IsNullOrEmpty(a.Title)).ToList()); //data.Add(select.Where(a => string.IsNullOrEmpty(a.Title) == false).ToList()); data.Add(select.Where(a => !string.IsNullOrEmpty(a.Title)).ToList()); + + data.Add(select.Where(a => string.IsNullOrEmpty(a.TitleVarchar)).ToList()); + //data.Add(select.Where(a => string.IsNullOrEmpty(a.TitleVarchar) == false).ToList()); + data.Add(select.Where(a => !string.IsNullOrEmpty(a.TitleVarchar)).ToList()); } [Fact] @@ -293,6 +424,10 @@ namespace FreeSql.Tests.SqlServerExpression data.Add(select.Where(a => string.IsNullOrWhiteSpace(a.Title)).ToList()); data.Add(select.Where(a => string.IsNullOrWhiteSpace(a.Title) == false).ToList()); data.Add(select.Where(a => !string.IsNullOrWhiteSpace(a.Title)).ToList()); + + data.Add(select.Where(a => string.IsNullOrWhiteSpace(a.TitleVarchar)).ToList()); + data.Add(select.Where(a => string.IsNullOrWhiteSpace(a.TitleVarchar) == false).ToList()); + data.Add(select.Where(a => !string.IsNullOrWhiteSpace(a.TitleVarchar)).ToList()); } } } diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index ff488d7c..dd964856 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -2000,6 +2000,137 @@ + + + 查询,若使用读写分离,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】 + + + + + + + + + 查询,ExecuteReaderAsync(dr => {}, "select * from user where age > @age", new { age = 25 }) + + + + + + + 查询 + + + + + + + 查询,ExecuteArrayAsync("select * from user where age > @age", new { age = 25 }) + + + + + + + + 查询 + + + + + + + 查询,ExecuteDataSetAsync("select * from user where age > @age; select 2", new { age = 25 }) + + + + + + + + 查询 + + + + + + + 查询,ExecuteDataTableAsync("select * from user where age > @age", new { age = 25 }) + + + + + + + + 在【主库】执行 + + + + + + + + 在【主库】执行,ExecuteNonQueryAsync("delete from user where age > @age", new { age = 25 }) + + + + + + + + 在【主库】执行 + + + + + + + + 在【主库】执行,ExecuteScalarAsync("select 1 from user where age > @age", new { age = 25 }) + + + + + + + + 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new SqlParameter { ParameterName = "age", Value = 25 }) + + + + + + + + + + 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new { age = 25 }) + + + + + + + + + 执行SQL返回对象集合,Query<User>("select * from user where age > @age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 }) + + + + + + + + + + 执行SQL返回对象集合,Query<User>("select * from user where age > @age; select * from address", new { age = 25 }) + + + + + + 可自定义解析表达式 diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index b83db6ff..759aaf19 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -332,7 +332,7 @@ namespace FreeSql.Internal var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, _selectColumnMap = _selectColumnMap, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, currentTable = table }); var isBool = exp.Type.NullableTypeOrThis() == typeof(bool); if (exp.NodeType == ExpressionType.MemberAccess && isBool && sql.Contains(" IS ") == false && sql.Contains(" = ") == false) - return $"{sql} = {formatSql(true, null)}"; + return $"{sql} = {formatSql(true, null, null)}"; if (isBool) return GetBoolString(sql); return sql; @@ -343,7 +343,7 @@ namespace FreeSql.Internal var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereCascadeExpression = whereCascadeExpression }); var isBool = exp.Type.NullableTypeOrThis() == typeof(bool); if (exp.NodeType == ExpressionType.MemberAccess && isBool && sql.Contains(" IS ") == false && sql.Contains(" = ") == false) - return $"{sql} = {formatSql(true, null)}"; + return $"{sql} = {formatSql(true, null, null)}"; if (isBool) return GetBoolString(sql); return sql; @@ -355,7 +355,7 @@ namespace FreeSql.Internal var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = tbtype, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereCascadeExpression = whereCascadeExpression }); var isBool = exp.Type.NullableTypeOrThis() == typeof(bool); if (exp.NodeType == ExpressionType.MemberAccess && isBool && sql.Contains(" IS ") == false && sql.Contains(" = ") == false) - sql = $"{sql} = {formatSql(true, null)}"; + sql = $"{sql} = {formatSql(true, null, null)}"; if (isBool) sql = GetBoolString(sql); @@ -433,7 +433,7 @@ namespace FreeSql.Internal { var enumType = leftMapColumn.CsType.NullableTypeOrThis(); if (enumType.IsEnum) - right = formatSql(Enum.Parse(enumType, right.StartsWith("N'") ? right.Substring(1).Trim('\'') : right.Trim('\'')), leftMapColumn.Attribute.MapType); + right = formatSql(Enum.Parse(enumType, right.StartsWith("N'") ? right.Substring(1).Trim('\'') : right.Trim('\'')), leftMapColumn.Attribute.MapType, leftMapColumn); } if (leftMapColumn == null) { @@ -447,7 +447,7 @@ namespace FreeSql.Internal { var enumType = rightMapColumn.CsType.NullableTypeOrThis(); if (enumType.IsEnum) - left = formatSql(Enum.Parse(enumType, left.StartsWith("N'") ? left.Substring(1).Trim('\'') : left.Trim('\'')), rightMapColumn.Attribute.MapType); + left = formatSql(Enum.Parse(enumType, left.StartsWith("N'") ? left.Substring(1).Trim('\'') : left.Trim('\'')), rightMapColumn.Attribute.MapType, rightMapColumn); } } } @@ -455,8 +455,8 @@ namespace FreeSql.Internal { if (oper == "=") { - var trueVal = formatSql(true, null); - var falseVal = formatSql(false, null); + var trueVal = formatSql(true, null, null); + var falseVal = formatSql(false, null, null); if (left == trueVal) return right; else if (left == falseVal) return $"not({right})"; else if (right == trueVal) return left; @@ -464,15 +464,14 @@ namespace FreeSql.Internal } else if (oper == "<>") { - var trueVal = formatSql(true, null); - var falseVal = formatSql(false, null); + var trueVal = formatSql(true, null, null); + var falseVal = formatSql(false, null, null); if (left == trueVal) return $"not({right})"; else if (left == falseVal) return right; else if (right == trueVal) return $"not({left})"; else if (right == falseVal) return left; } } - if (left == "NULL") { var tmp = right; @@ -488,9 +487,9 @@ namespace FreeSql.Internal break; case "AND": case "OR": - if (leftMapColumn != null) left = $"{left} = {formatSql(true, null)}"; + if (leftMapColumn != null) left = $"{left} = {formatSql(true, null, null)}"; else left = GetBoolString(left); - if (rightMapColumn != null) right = $"{right} = {formatSql(true, null)}"; + if (rightMapColumn != null) right = $"{right} = {formatSql(true, null, null)}"; else right = GetBoolString(right); break; } @@ -517,7 +516,7 @@ namespace FreeSql.Internal if (notBody.Contains(" IS NOT NULL")) return notBody.Replace(" IS NOT NULL", " IS NULL"); if (notBody.Contains("=")) return notBody.Replace("=", "!="); if (notBody.Contains("!=")) return notBody.Replace("!=", "="); - return $"{notBody} = {formatSql(false, null)}"; + return $"{notBody} = {formatSql(false, null, null)}"; } return $"not({ExpressionLambdaToSql(notExp, tsc)})"; case ExpressionType.Quote: return ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, tsc); @@ -529,7 +528,7 @@ namespace FreeSql.Internal return ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, tsc); case ExpressionType.Negate: case ExpressionType.NegateChecked: return "-" + ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, tsc); - case ExpressionType.Constant: return formatSql((exp as ConstantExpression)?.Value, tsc.mapType); + case ExpressionType.Constant: return formatSql((exp as ConstantExpression)?.Value, tsc.mapType, tsc.mapColumnTmp); case ExpressionType.Conditional: var condExp = exp as ConditionalExpression; return $"case when {ExpressionLambdaToSql(condExp.Test, tsc)} then {ExpressionLambdaToSql(condExp.IfTrue, tsc)} else {ExpressionLambdaToSql(condExp.IfFalse, tsc)} end"; @@ -855,7 +854,7 @@ namespace FreeSql.Internal //} other3Exp = ExpressionLambdaToSqlOther(exp3, tsc); if (string.IsNullOrEmpty(other3Exp) == false) return other3Exp; - if (exp3.IsParameter() == false) return formatSql(Expression.Lambda(exp3).Compile().DynamicInvoke(), tsc.mapType); + if (exp3.IsParameter() == false) return formatSql(Expression.Lambda(exp3).Compile().DynamicInvoke(), tsc.mapType, tsc.mapColumnTmp); throw new Exception($"未实现函数表达式 {exp3} 解析"); case ExpressionType.Parameter: case ExpressionType.MemberAccess: @@ -915,7 +914,7 @@ namespace FreeSql.Internal } break; } - if (expStack.First().NodeType != ExpressionType.Parameter) return formatSql(Expression.Lambda(exp).Compile().DynamicInvoke(), tsc.mapType); + if (expStack.First().NodeType != ExpressionType.Parameter) return formatSql(Expression.Lambda(exp).Compile().DynamicInvoke(), tsc.mapType, tsc.mapColumnTmp); if (callExp != null) return ExpressionLambdaToSql(callExp, tsc); if (tsc.getSelectGroupingMapString != null && expStack.First().Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) { @@ -942,7 +941,7 @@ namespace FreeSql.Internal tsc._selectColumnMap.Add(new SelectColumnInfo { Table = null, Column = curcol }); var name = curcol.Attribute.Name; if (tsc.isQuoteName) name = _common.QuoteSqlName(name); - tsc.mapTypeTmp = curcol.Attribute.MapType == curcol.CsType ? null : curcol.Attribute.MapType; + tsc.SetMapColumnTmp(curcol); if (string.IsNullOrEmpty(tsc.alias001)) return name; return $"{tsc.alias001}.{name}"; } @@ -1104,7 +1103,7 @@ namespace FreeSql.Internal return ""; } name2 = col2.Attribute.Name; - tsc.mapTypeTmp = col2.Attribute.MapType == col2.CsType ? null : col2.Attribute.MapType; + tsc.SetMapColumnTmp(col2); break; case ExpressionType.Call: break; } @@ -1126,7 +1125,7 @@ namespace FreeSql.Internal } if (dicExpressionOperator.TryGetValue(expBinary.NodeType, out var tryoper) == false) { - if (exp.IsParameter() == false) return formatSql(Expression.Lambda(exp).Compile().DynamicInvoke(), tsc.mapType); + if (exp.IsParameter() == false) return formatSql(Expression.Lambda(exp).Compile().DynamicInvoke(), tsc.mapType, tsc.mapColumnTmp); return ""; } return ExpressionBinary(tryoper, expBinary.Left, expBinary.Right, tsc); @@ -1157,13 +1156,24 @@ namespace FreeSql.Internal public ExpressionStyle style { get; set; } public Type mapType { get; set; } public Type mapTypeTmp { get; set; } + public ColumnInfo mapColumnTmp { get; set; } public TableInfo currentTable { get; set; } public List whereCascadeExpression { get; set; } public string alias001 { get; set; } //单表字段的表别名 - public void SetMapTypeTmp(Type newValue) + public ExpTSC SetMapColumnTmp(ColumnInfo col) { - this.mapTypeTmp = null; + if (col == null) + { + this.mapTypeTmp = null; + this.mapColumnTmp = null; + } + else + { + this.mapTypeTmp = col.Attribute.MapType == col.CsType ? null : col.Attribute.MapType; + this.mapColumnTmp = col; + } + return this; } public Type SetMapTypeReturnOld(Type newValue) { @@ -1263,6 +1273,6 @@ namespace FreeSql.Internal } } - public string formatSql(object obj, Type mapType) => string.Concat(_ado.AddslashesProcessParam(obj, mapType)); + public string formatSql(object obj, Type mapType, ColumnInfo mapColumn) => string.Concat(_ado.AddslashesProcessParam(obj, mapType, mapColumn)); } } diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderUtils.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderUtils.cs index 4d5aae64..56c43677 100644 --- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderUtils.cs +++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderUtils.cs @@ -1,4 +1,5 @@ -using System; +using FreeSql.Internal.Model; +using System; using System.Collections.Concurrent; using System.Text.RegularExpressions; @@ -6,7 +7,7 @@ namespace FreeSql.Internal.CommonProvider { partial class AdoProvider { - public abstract object AddslashesProcessParam(object param, Type mapType); + public abstract object AddslashesProcessParam(object param, Type mapType, ColumnInfo mapColumn); public string Addslashes(string filter, params object[] parms) { if (filter == null || parms == null) return string.Empty; @@ -17,7 +18,7 @@ namespace FreeSql.Internal.CommonProvider if (parms[a] == null) filter = _dicAddslashesReplaceIsNull.GetOrAdd(a, b => new Regex(@"\s*(=|IN)\s*\{" + b + @"\}", RegexOptions.IgnoreCase | RegexOptions.Compiled)) .Replace(filter, $" IS {{{a}}}"); - nparms[a] = AddslashesProcessParam(parms[a], null); + nparms[a] = AddslashesProcessParam(parms[a], null, null); } try { string ret = string.Format(filter, nparms); return ret; } catch { return filter; } } diff --git a/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlAdo.cs b/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlAdo.cs index e061fe23..602ed684 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlAdo.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlAdo.cs @@ -1,4 +1,5 @@ using FreeSql.Internal; +using FreeSql.Internal.Model; using MySql.Data.MySqlClient; using SafeObjectPool; using System; @@ -28,7 +29,7 @@ namespace FreeSql.MySql } } static DateTime dt1970 = new DateTime(1970, 1, 1); - public override object AddslashesProcessParam(object param, Type mapType) + public override object AddslashesProcessParam(object param, Type mapType, ColumnInfo mapColumn) { if (param == null) return "NULL"; if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) @@ -51,7 +52,7 @@ namespace FreeSql.MySql { var sb = new StringBuilder(); var ie = param as IEnumerable; - foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType)); + foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType, mapColumn)); return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString(); } return string.Concat("'", param.ToString().Replace("'", "''"), "'"); diff --git a/Providers/FreeSql.Provider.MySql/MySqlExpression.cs b/Providers/FreeSql.Provider.MySql/MySqlExpression.cs index b795dbaf..2f3f78a8 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlExpression.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlExpression.cs @@ -101,11 +101,11 @@ namespace FreeSql.MySql if (objType == null) objType = callExp.Method.DeclaringType; if (objType != null || objType.IsArrayOrList()) { - tsc?.SetMapTypeTmp(null); + tsc.SetMapColumnTmp(null); var args1 = getExp(callExp.Arguments[argIndex]); - var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); + var oldMapType = tsc.SetMapTypeReturnOld(tsc.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); - tsc.SetMapTypeReturnOld(oldMapType); + tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": diff --git a/Providers/FreeSql.Provider.Odbc/Default/OdbcAdapter.cs b/Providers/FreeSql.Provider.Odbc/Default/OdbcAdapter.cs index 6eade116..ddddb518 100644 --- a/Providers/FreeSql.Provider.Odbc/Default/OdbcAdapter.cs +++ b/Providers/FreeSql.Provider.Odbc/Default/OdbcAdapter.cs @@ -1,4 +1,5 @@ -using System; +using FreeSql.Internal.Model; +using System; using System.Collections.Generic; using System.Text; @@ -43,7 +44,7 @@ namespace FreeSql.Odbc.Default public virtual char QuoteSqlNameRight => ']'; public virtual string FieldSql(Type type, string columnName) => columnName; - public virtual string UnicodeStringRawSql(object value) => value == null ? "NULL" : string.Concat("N'", value.ToString().Replace("'", "''"), "'"); + public virtual string UnicodeStringRawSql(object value, ColumnInfo mapColumn) => value == null ? "NULL" : string.Concat("N'", value.ToString().Replace("'", "''"), "'"); public virtual string DateTimeRawSql(object value) { if (value == null) return "NULL"; diff --git a/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs b/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs index b42c5b48..2d7a2b0e 100644 --- a/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs @@ -1,4 +1,5 @@ using FreeSql.Internal; +using FreeSql.Internal.Model; using SafeObjectPool; using System; using System.Collections; @@ -29,7 +30,7 @@ namespace FreeSql.Odbc.Default OdbcAdapter Adapter => (_util == null ? FreeSqlOdbcGlobalExtensions.DefaultOdbcAdapter : _util._orm.GetOdbcAdapter()); static DateTime dt1970 = new DateTime(1970, 1, 1); - public override object AddslashesProcessParam(object param, Type mapType) + public override object AddslashesProcessParam(object param, Type mapType, ColumnInfo mapColumn) { if (param == null) return "NULL"; if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) @@ -37,7 +38,7 @@ namespace FreeSql.Odbc.Default if (param is bool || param is bool?) return (bool)param ? 1 : 0; else if (param is string) - return Adapter.UnicodeStringRawSql(param); + return Adapter.UnicodeStringRawSql(param, mapColumn); else if (param is char) return string.Concat("'", param.ToString().Replace("'", "''"), "'"); else if (param is Enum) @@ -52,7 +53,7 @@ namespace FreeSql.Odbc.Default { var sb = new StringBuilder(); var ie = param as IEnumerable; - foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType)); + foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType, mapColumn)); return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString(); } return string.Concat("'", param.ToString().Replace("'", "''"), "'"); diff --git a/Providers/FreeSql.Provider.Odbc/Default/OdbcExpression.cs b/Providers/FreeSql.Provider.Odbc/Default/OdbcExpression.cs index 574455f7..4d2bf9ea 100644 --- a/Providers/FreeSql.Provider.Odbc/Default/OdbcExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/Default/OdbcExpression.cs @@ -108,11 +108,11 @@ namespace FreeSql.Odbc.Default if (objType == null) objType = callExp.Method.DeclaringType; if (objType != null || objType.IsArrayOrList()) { - tsc?.SetMapTypeTmp(null); + tsc.SetMapColumnTmp(null); var args1 = getExp(callExp.Arguments[argIndex]); - var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); + var oldMapType = tsc.SetMapTypeReturnOld(tsc.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); - tsc.SetMapTypeReturnOld(oldMapType); + tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs index 0cd07d54..0aa06d1a 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs @@ -1,4 +1,5 @@ using FreeSql.Internal; +using FreeSql.Internal.Model; using SafeObjectPool; using System; using System.Collections; @@ -28,7 +29,7 @@ namespace FreeSql.Odbc.MySql } } static DateTime dt1970 = new DateTime(1970, 1, 1); - public override object AddslashesProcessParam(object param, Type mapType) + public override object AddslashesProcessParam(object param, Type mapType, ColumnInfo mapColumn) { if (param == null) return "NULL"; if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) @@ -49,7 +50,7 @@ namespace FreeSql.Odbc.MySql { var sb = new StringBuilder(); var ie = param as IEnumerable; - foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType)); + foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType, mapColumn)); return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString(); } return string.Concat("'", param.ToString().Replace("'", "''"), "'"); diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs index 2bcd91b2..14bce855 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs @@ -101,11 +101,11 @@ namespace FreeSql.Odbc.MySql if (objType == null) objType = callExp.Method.DeclaringType; if (objType != null || objType.IsArrayOrList()) { - tsc?.SetMapTypeTmp(null); + tsc.SetMapColumnTmp(null); var args1 = getExp(callExp.Arguments[argIndex]); - var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); + var oldMapType = tsc.SetMapTypeReturnOld(tsc.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); - tsc.SetMapTypeReturnOld(oldMapType); + tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleAdo.cs b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleAdo.cs index 1bb9cfe0..6a3cd58b 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleAdo.cs @@ -1,4 +1,5 @@ using FreeSql.Internal; +using FreeSql.Internal.Model; using SafeObjectPool; using System; using System.Collections; @@ -27,7 +28,7 @@ namespace FreeSql.Odbc.Oracle } } static DateTime dt1970 = new DateTime(1970, 1, 1); - public override object AddslashesProcessParam(object param, Type mapType) + public override object AddslashesProcessParam(object param, Type mapType, ColumnInfo mapColumn) { if (param == null) return "NULL"; if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) @@ -48,7 +49,7 @@ namespace FreeSql.Odbc.Oracle { var sb = new StringBuilder(); var ie = param as IEnumerable; - foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType)); + foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType, mapColumn)); return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString(); } return string.Concat("'", param.ToString().Replace("'", "''"), "'"); diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleExpression.cs b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleExpression.cs index 1c9f08e4..651fbef3 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleExpression.cs @@ -101,11 +101,11 @@ namespace FreeSql.Odbc.Oracle if (objType == null) objType = callExp.Method.DeclaringType; if (objType != null || objType.IsArrayOrList()) { - tsc?.SetMapTypeTmp(null); + tsc.SetMapColumnTmp(null); var args1 = getExp(callExp.Arguments[argIndex]); - var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); + var oldMapType = tsc.SetMapTypeReturnOld(tsc.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); - tsc.SetMapTypeReturnOld(oldMapType); + tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": diff --git a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs index 0d7027a6..862ea601 100644 --- a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs @@ -1,4 +1,5 @@ using FreeSql.Internal; +using FreeSql.Internal.Model; using SafeObjectPool; using System; using System.Collections; @@ -29,7 +30,7 @@ namespace FreeSql.Odbc.PostgreSQL } static DateTime dt1970 = new DateTime(1970, 1, 1); - public override object AddslashesProcessParam(object param, Type mapType) + public override object AddslashesProcessParam(object param, Type mapType, ColumnInfo mapColumn) { if (param == null) return "NULL"; if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) @@ -50,7 +51,7 @@ namespace FreeSql.Odbc.PostgreSQL { var sb = new StringBuilder(); var ie = param as IEnumerable; - foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType)); + foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType, mapColumn)); return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString(); } return string.Concat("'", param.ToString().Replace("'", "''"), "'"); diff --git a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLExpression.cs b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLExpression.cs index cc7839cb..28da1107 100644 --- a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLExpression.cs @@ -130,11 +130,11 @@ namespace FreeSql.Odbc.PostgreSQL if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]"; return $"(case when {left} is null then 0 else array_length({left},1) end > 0)"; case "Contains": - tsc?.SetMapTypeTmp(null); + tsc.SetMapColumnTmp(null); var args1 = getExp(callExp.Arguments[argIndex]); - var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); + var oldMapType = tsc.SetMapTypeReturnOld(tsc.mapTypeTmp); left = objExp == null ? null : getExp(objExp); - tsc.SetMapTypeReturnOld(oldMapType); + tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType); //判断 in 或 array @> array if (left.StartsWith("array[") || left.EndsWith("]")) return $"{args1} in ({left.Substring(6, left.Length - 7)})"; diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerAdo.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerAdo.cs index 3920f4b6..4ee2b561 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerAdo.cs @@ -1,9 +1,11 @@ using FreeSql.Internal; +using FreeSql.Internal.Model; using SafeObjectPool; using System; using System.Collections; using System.Data.Common; using System.Data.Odbc; +using System.Linq; using System.Text; using System.Threading; @@ -26,8 +28,10 @@ namespace FreeSql.Odbc.SqlServer } } } + static DateTime dt1970 = new DateTime(1970, 1, 1); - public override object AddslashesProcessParam(object param, Type mapType) + string[] ncharDbTypes = new[] { "NVARCHAR", "NCHAR", "NTEXT" }; + public override object AddslashesProcessParam(object param, Type mapType, ColumnInfo mapColumn) { if (param == null) return "NULL"; if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) @@ -35,7 +39,11 @@ namespace FreeSql.Odbc.SqlServer if (param is bool || param is bool?) return (bool)param ? 1 : 0; else if (param is string) + { + if (mapColumn != null && mapColumn.CsType.NullableTypeOrThis() == typeof(string) && ncharDbTypes.Any(a => mapColumn.Attribute.DbType.Contains(a)) == false) + return string.Concat("'", param.ToString().Replace("'", "''"), "'"); return string.Concat("N'", param.ToString().Replace("'", "''"), "'"); + } else if (param is char) return string.Concat("'", param.ToString().Replace("'", "''"), "'"); else if (param is Enum) @@ -58,7 +66,7 @@ namespace FreeSql.Odbc.SqlServer { var sb = new StringBuilder(); var ie = param as IEnumerable; - foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType)); + foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType, mapColumn)); return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString(); } return string.Concat("'", param.ToString().Replace("'", "''"), "'"); diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs index 74a752c9..7c1712bc 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs @@ -105,11 +105,11 @@ namespace FreeSql.Odbc.SqlServer if (objType == null) objType = callExp.Method.DeclaringType; if (objType != null || objType.IsArrayOrList()) { - tsc?.SetMapTypeTmp(null); + tsc.SetMapColumnTmp(null); var args1 = getExp(callExp.Arguments[argIndex]); - var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); + var oldMapType = tsc.SetMapTypeReturnOld(tsc.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); - tsc.SetMapTypeReturnOld(oldMapType); + tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": diff --git a/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleAdo.cs b/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleAdo.cs index 8c45bb19..424b8175 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleAdo.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleAdo.cs @@ -1,4 +1,5 @@ using FreeSql.Internal; +using FreeSql.Internal.Model; using Oracle.ManagedDataAccess.Client; using SafeObjectPool; using System; @@ -27,7 +28,7 @@ namespace FreeSql.Oracle } } static DateTime dt1970 = new DateTime(1970, 1, 1); - public override object AddslashesProcessParam(object param, Type mapType) + public override object AddslashesProcessParam(object param, Type mapType, ColumnInfo mapColumn) { if (param == null) return "NULL"; if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) @@ -48,7 +49,7 @@ namespace FreeSql.Oracle { var sb = new StringBuilder(); var ie = param as IEnumerable; - foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType)); + foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType, mapColumn)); return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString(); } return string.Concat("'", param.ToString().Replace("'", "''"), "'"); diff --git a/Providers/FreeSql.Provider.Oracle/OracleExpression.cs b/Providers/FreeSql.Provider.Oracle/OracleExpression.cs index a5f35911..818dff2b 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleExpression.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleExpression.cs @@ -101,11 +101,11 @@ namespace FreeSql.Oracle if (objType == null) objType = callExp.Method.DeclaringType; if (objType != null || objType.IsArrayOrList()) { - tsc?.SetMapTypeTmp(null); + tsc.SetMapColumnTmp(null); var args1 = getExp(callExp.Arguments[argIndex]); - var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); + var oldMapType = tsc.SetMapTypeReturnOld(tsc.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); - tsc.SetMapTypeReturnOld(oldMapType); + tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": diff --git a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs index eee3e5c9..ae3c9e3f 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs @@ -1,4 +1,5 @@ using FreeSql.Internal; +using FreeSql.Internal.Model; using Newtonsoft.Json.Linq; using Npgsql; using SafeObjectPool; @@ -30,7 +31,7 @@ namespace FreeSql.PostgreSQL } static DateTime dt1970 = new DateTime(1970, 1, 1); - public override object AddslashesProcessParam(object param, Type mapType) + public override object AddslashesProcessParam(object param, Type mapType, ColumnInfo mapColumn) { if (param == null) return "NULL"; if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList() || param is JToken || param is JObject || param is JArray)) @@ -67,7 +68,7 @@ namespace FreeSql.PostgreSQL { var sb = new StringBuilder(); var ie = param as IEnumerable; - foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType)); + foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType, mapColumn)); return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString(); } return string.Concat("'", param.ToString().Replace("'", "''"), "'"); diff --git a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExpression.cs b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExpression.cs index 4507cebe..86760acc 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExpression.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExpression.cs @@ -160,11 +160,11 @@ namespace FreeSql.PostgreSQL if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]"; return $"(case when {left} is null then 0 else array_length({left},1) end > 0)"; case "Contains": - tsc?.SetMapTypeTmp(null); + tsc.SetMapColumnTmp(null); var args1 = getExp(callExp.Arguments[argIndex]); - var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); + var oldMapType = tsc.SetMapTypeReturnOld(tsc.mapTypeTmp); left = objExp == null ? null : getExp(objExp); - tsc.SetMapTypeReturnOld(oldMapType); + tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType); //判断 in 或 array @> array if (left.StartsWith("array[") || left.EndsWith("]")) return $"{args1} in ({left.Substring(6, left.Length - 7)})"; diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerAdo.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerAdo.cs index c6799a13..b6e43640 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerAdo.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerAdo.cs @@ -1,9 +1,11 @@ using FreeSql.Internal; +using FreeSql.Internal.Model; using SafeObjectPool; using System; using System.Collections; using System.Data.Common; using System.Data.SqlClient; +using System.Linq; using System.Text; using System.Threading; @@ -26,8 +28,10 @@ namespace FreeSql.SqlServer } } } + static DateTime dt1970 = new DateTime(1970, 1, 1); - public override object AddslashesProcessParam(object param, Type mapType) + static string[] ncharDbTypes = new[] { "NVARCHAR", "NCHAR", "NTEXT" }; + public override object AddslashesProcessParam(object param, Type mapType, ColumnInfo mapColumn) { if (param == null) return "NULL"; if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) @@ -35,7 +39,11 @@ namespace FreeSql.SqlServer if (param is bool || param is bool?) return (bool)param ? 1 : 0; else if (param is string) + { + if (mapColumn != null && mapColumn.CsType.NullableTypeOrThis() == typeof(string) && ncharDbTypes.Any(a => mapColumn.Attribute.DbType.Contains(a)) == false) + return string.Concat("'", param.ToString().Replace("'", "''"), "'"); return string.Concat("N'", param.ToString().Replace("'", "''"), "'"); + } else if (param is char) return string.Concat("'", param.ToString().Replace("'", "''"), "'"); else if (param is Enum) @@ -58,7 +66,7 @@ namespace FreeSql.SqlServer { var sb = new StringBuilder(); var ie = param as IEnumerable; - foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType)); + foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType, mapColumn)); return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString(); } return string.Concat("'", param.ToString().Replace("'", "''"), "'"); diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs index c775851f..85edc86a 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs @@ -105,11 +105,11 @@ namespace FreeSql.SqlServer if (objType == null) objType = callExp.Method.DeclaringType; if (objType != null || objType.IsArrayOrList()) { - tsc?.SetMapTypeTmp(null); + tsc.SetMapColumnTmp(null); var args1 = getExp(callExp.Arguments[argIndex]); - var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); + var oldMapType = tsc.SetMapTypeReturnOld(tsc.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); - tsc.SetMapTypeReturnOld(oldMapType); + tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteAdo.cs b/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteAdo.cs index 9e27fc13..b8175943 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteAdo.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteAdo.cs @@ -1,4 +1,5 @@ using FreeSql.Internal; +using FreeSql.Internal.Model; using SafeObjectPool; using System; using System.Collections; @@ -26,7 +27,7 @@ namespace FreeSql.Sqlite } } static DateTime dt1970 = new DateTime(1970, 1, 1); - public override object AddslashesProcessParam(object param, Type mapType) + public override object AddslashesProcessParam(object param, Type mapType, ColumnInfo mapColumn) { if (param == null) return "NULL"; if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) @@ -47,7 +48,7 @@ namespace FreeSql.Sqlite { var sb = new StringBuilder(); var ie = param as IEnumerable; - foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType)); + foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType, mapColumn)); return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString(); } return string.Concat("'", param.ToString().Replace("'", "''"), "'"); diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs b/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs index ce13a196..1c2f821d 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs @@ -101,11 +101,11 @@ namespace FreeSql.Sqlite if (objType == null) objType = callExp.Method.DeclaringType; if (objType != null || objType.IsArrayOrList()) { - tsc?.SetMapTypeTmp(null); + tsc.SetMapColumnTmp(null); var args1 = getExp(callExp.Arguments[argIndex]); - var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); + var oldMapType = tsc.SetMapTypeReturnOld(tsc.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); - tsc.SetMapTypeReturnOld(oldMapType); + tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains":