diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Duckdb/Duckdb/DuckdbCodeFirstTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Duckdb/Duckdb/DuckdbCodeFirstTest.cs index 082c86723..7287a66e3 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Duckdb/Duckdb/DuckdbCodeFirstTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Duckdb/Duckdb/DuckdbCodeFirstTest.cs @@ -17,6 +17,15 @@ public class DuckdbCodeFirstTest IFreeSql fsql => g.duckdb; + [Fact] + public void CompositeTypeCrud() + { + } + public class test_CompositeTypeCrud + { + public Dictionary testFieldStruct { get; set; } + } + [Fact] public void DateOnlyTimeOnly() { @@ -41,7 +50,7 @@ public void DateOnlyTimeOnly() var sqlPar = fsql.Insert(item2).ToSql(); var sqlText = fsql.Insert(item2).NoneParameter().ToSql(); - Assert.Equal(sqlText, "INSERT INTO \"test_dateonlytimeonly01\"(\"testfieldtimespan\", \"testfieldtimeonly\", \"testfielddatetime\", \"testfielddateonly\", \"testfieldtimespannullable\", \"testfieldtimeonlynullable\", \"testfielddatetimenullable\", \"testfielddateonlynullable\") VALUES(time '16:0:0.0', time '11:0:0', current_timestamp, date '2024-08-20', time '0:1:30.0', time '0:1:30', current_timestamp, date '2024-08-19')"); + Assert.Equal("INSERT INTO \"test_dateonlytimeonly01\"(\"testfieldtimespan\", \"testfieldtimeonly\", \"testfielddatetime\", \"testfielddateonly\", \"testfieldtimespannullable\", \"testfieldtimeonlynullable\", \"testfielddatetimenullable\", \"testfielddateonlynullable\") VALUES(time '16:0:0.0', time '11:0:0', current_timestamp, date '2024-08-20', time '0:1:30.0', time '0:1:30', current_timestamp, date '2024-08-19')", sqlText); item2.Id = (int)fsql.Insert(item2).NoneParameter().ExecuteIdentity(); var item3NP = fsql.Select().Where(a => a.Id == item2.Id).ToOne(); Assert.Equal(item3NP.testFieldDateOnly, item2.testFieldDateOnly); @@ -78,6 +87,78 @@ class test_DateOnlyTimeOnly01 public DateOnly? testFieldDateOnlyNullable { get; set; } } + [Fact] + public void DateOnlyTimeOnlyArrayTypeCrud() + { + var item = new test_DateOnlyTimeOnlyArrayTypeCrud { }; + item.Id = (int)fsql.Insert(item).ExecuteIdentity(); + + var newitem = fsql.Select().Where(a => a.Id == item.Id).ToOne(); + + var now = DateTime.Parse("2024-8-20 23:00:11"); + var item2 = new test_DateOnlyTimeOnlyArrayTypeCrud + { + testFieldDateTimeArray = new[] { now, now.AddHours(2) }, + testFieldDateTimeArrayNullable = new DateTime?[] { now, null, now.AddHours(2) }, + testFieldDateOnlyArray = new[] { DateOnly.FromDateTime(now), DateOnly.FromDateTime(now.AddHours(2)) }, + testFieldDateOnlyArrayNullable = new DateOnly?[] { DateOnly.FromDateTime(now), null, DateOnly.FromDateTime(now.AddHours(2)) }, + + testFieldTimeSpanArray = new[] { TimeSpan.FromHours(11), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(60) }, + testFieldTimeSpanArrayNullable = new TimeSpan?[] { TimeSpan.FromHours(11), TimeSpan.FromSeconds(10), null, TimeSpan.FromSeconds(60) }, + testFieldTimeOnlyArray = new[] { TimeOnly.FromTimeSpan(TimeSpan.FromHours(11)), TimeOnly.FromTimeSpan(TimeSpan.FromSeconds(10)), TimeOnly.FromTimeSpan(TimeSpan.FromSeconds(60)) }, + testFieldTimeOnlyArrayNullable = new TimeOnly?[] { TimeOnly.FromTimeSpan(TimeSpan.FromHours(11)), TimeOnly.FromTimeSpan(TimeSpan.FromSeconds(10)), null, TimeOnly.FromTimeSpan(TimeSpan.FromSeconds(60)) }, + }; + + var sqlText = fsql.Insert(item2).NoneParameter().ToSql(); + Assert.Equal("INSERT INTO \"test_dateonlytimeonlyarraytypecrud\"(\"testfieldtimespanarray\", \"testfieldtimeonlyarray\", \"testfielddatetimearray\", \"testfielddateonlyarray\", \"testfieldtimespanarraynullable\", \"testfieldtimeonlyarraynullable\", \"testfielddatetimearraynullable\", \"testfielddateonlyarraynullable\") VALUES([time '11:0:0.0',time '0:0:10.0',time '0:1:0.0'], [time '11:0:0',time '0:0:10',time '0:1:0'], [timestamp '2024-08-20 23:00:11.000000',timestamp '2024-08-21 01:00:11.000000'], [date '2024-08-20',date '2024-08-21'], [time '11:0:0.0',time '0:0:10.0',time '0:0:0.0',time '0:1:0.0'], [time '11:0:0',time '0:0:10',time '0:0:0',time '0:1:0'], [timestamp '2024-08-20 23:00:11.000000',timestamp '0001-01-01 00:00:00.000000',timestamp '2024-08-21 01:00:11.000000'], [date '2024-08-20',date '0001-01-01',date '2024-08-21'])", sqlText); + item2.Id = (int)fsql.Insert(item2).NoneParameter().ExecuteIdentity(); + var item3NP = fsql.Select().Where(a => a.Id == item2.Id).ToOne(); + Assert.Equal(item3NP.Id, item2.Id); + Assert.Equal("2024-08-20 23:00:11, 2024-08-21 01:00:11", string.Join(", ", item3NP.testFieldDateTimeArray.Select(a => a.ToString("yyyy-MM-dd HH:mm:ss")))); + Assert.Equal("2024-08-20 23:00:11, 0001-01-01 00:00:00, 2024-08-21 01:00:11", string.Join(", ", item3NP.testFieldDateTimeArrayNullable.Select(a => a?.ToString("yyyy-MM-dd HH:mm:ss")))); + Assert.Equal("2024-08-20, 2024-08-21", string.Join(", ", item3NP.testFieldDateOnlyArray.Select(a => a.ToString("yyyy-MM-dd")))); + Assert.Equal("2024-08-20, 0001-01-01, 2024-08-21", string.Join(", ", item3NP.testFieldDateOnlyArrayNullable.Select(a => a?.ToString("yyyy-MM-dd")))); + + Assert.Equal("11:00:00, 00:00:10, 00:01:00", string.Join(", ", item3NP.testFieldTimeSpanArray.Select(a => $"{a.Hours.ToString().PadLeft(2, '0')}:{a.Minutes.ToString().PadLeft(2, '0')}:{a.Seconds.ToString().PadLeft(2, '0')}"))); + Assert.Equal("11:00:00, 00:00:10, 00:00:00, 00:01:00", string.Join(", ", item3NP.testFieldTimeSpanArrayNullable.Select(a => $"{a?.Hours.ToString().PadLeft(2, '0')}:{a?.Minutes.ToString().PadLeft(2, '0')}:{a?.Seconds.ToString().PadLeft(2, '0')}"))); + Assert.Equal("11:00:00, 00:00:10, 00:01:00", string.Join(", ", item3NP.testFieldTimeOnlyArray.Select(a => $"{a.Hour.ToString().PadLeft(2, '0')}:{a.Minute.ToString().PadLeft(2, '0')}:{a.Second.ToString().PadLeft(2, '0')}"))); + Assert.Equal("11:00:00, 00:00:10, 00:00:00, 00:01:00", string.Join(", ", item3NP.testFieldTimeOnlyArrayNullable.Select(a => $"{a?.Hour.ToString().PadLeft(2, '0')}:{a?.Minute.ToString().PadLeft(2, '0')}:{a?.Second.ToString().PadLeft(2, '0')}"))); + + sqlText = fsql.Insert(item2).ToSql(); + Assert.Equal("INSERT INTO \"test_dateonlytimeonlyarraytypecrud\"(\"testfieldtimespanarray\", \"testfieldtimeonlyarray\", \"testfielddatetimearray\", \"testfielddateonlyarray\", \"testfieldtimespanarraynullable\", \"testfieldtimeonlyarraynullable\", \"testfielddatetimearraynullable\", \"testfielddateonlyarraynullable\") VALUES([time '11:0:0.0',time '0:0:10.0',time '0:1:0.0'], [time '11:0:0',time '0:0:10',time '0:1:0'], [timestamp '2024-08-20 23:00:11.000000',timestamp '2024-08-21 01:00:11.000000'], [date '2024-08-20',date '2024-08-21'], [time '11:0:0.0',time '0:0:10.0',time '0:0:0.0',time '0:1:0.0'], [time '11:0:0',time '0:0:10',time '0:0:0',time '0:1:0'], [timestamp '2024-08-20 23:00:11.000000',timestamp '0001-01-01 00:00:00.000000',timestamp '2024-08-21 01:00:11.000000'], [date '2024-08-20',date '0001-01-01',date '2024-08-21'])", sqlText); + item2.Id = (int)fsql.Insert(item2).ExecuteIdentity(); + item3NP = fsql.Select().Where(a => a.Id == item2.Id).ToOne(); + Assert.Equal(item3NP.Id, item2.Id); + Assert.Equal("2024-08-20 23:00:11, 2024-08-21 01:00:11", string.Join(", ", item3NP.testFieldDateTimeArray.Select(a => a.ToString("yyyy-MM-dd HH:mm:ss")))); + Assert.Equal("2024-08-20 23:00:11, 0001-01-01 00:00:00, 2024-08-21 01:00:11", string.Join(", ", item3NP.testFieldDateTimeArrayNullable.Select(a => a?.ToString("yyyy-MM-dd HH:mm:ss")))); + Assert.Equal("2024-08-20, 2024-08-21", string.Join(", ", item3NP.testFieldDateOnlyArray.Select(a => a.ToString("yyyy-MM-dd")))); + Assert.Equal("2024-08-20, 0001-01-01, 2024-08-21", string.Join(", ", item3NP.testFieldDateOnlyArrayNullable.Select(a => a?.ToString("yyyy-MM-dd")))); + + + Assert.Equal("11:00:00, 00:00:10, 00:01:00", string.Join(", ", item3NP.testFieldTimeSpanArray.Select(a => $"{a.Hours.ToString().PadLeft(2, '0')}:{a.Minutes.ToString().PadLeft(2, '0')}:{a.Seconds.ToString().PadLeft(2, '0')}"))); + Assert.Equal("11:00:00, 00:00:10, 00:00:00, 00:01:00", string.Join(", ", item3NP.testFieldTimeSpanArrayNullable.Select(a => $"{a?.Hours.ToString().PadLeft(2, '0')}:{a?.Minutes.ToString().PadLeft(2, '0')}:{a?.Seconds.ToString().PadLeft(2, '0')}"))); + Assert.Equal("11:00:00, 00:00:10, 00:01:00", string.Join(", ", item3NP.testFieldTimeOnlyArray.Select(a => $"{a.Hour.ToString().PadLeft(2, '0')}:{a.Minute.ToString().PadLeft(2, '0')}:{a.Second.ToString().PadLeft(2, '0')}"))); + Assert.Equal("11:00:00, 00:00:10, 00:00:00, 00:01:00", string.Join(", ", item3NP.testFieldTimeOnlyArrayNullable.Select(a => $"{a?.Hour.ToString().PadLeft(2, '0')}:{a?.Minute.ToString().PadLeft(2, '0')}:{a?.Second.ToString().PadLeft(2, '0')}"))); + + var items = fsql.Select().ToList(); + var itemstb = fsql.Select().ToDataTable(); + } + class test_DateOnlyTimeOnlyArrayTypeCrud + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + + public TimeSpan[] testFieldTimeSpanArray { get; set; } + public TimeOnly[] testFieldTimeOnlyArray { get; set; } + public DateTime[] testFieldDateTimeArray { get; set; } + public DateOnly[] testFieldDateOnlyArray { get; set; } + + public TimeSpan?[] testFieldTimeSpanArrayNullable { get; set; } + public TimeOnly?[] testFieldTimeOnlyArrayNullable { get; set; } + public DateTime?[] testFieldDateTimeArrayNullable { get; set; } + public DateOnly?[] testFieldDateOnlyArrayNullable { get; set; } + } + [Fact] public void UInt256Crud2() { @@ -123,6 +204,437 @@ class tuint256tb_01 public BigInteger Number { get; set; } } + [Fact] + public void NumberTypeCrud() + { + var item = new test_NumberTypeCrud { }; + item.Id = (int)fsql.Insert(item).ExecuteIdentity(); + + var newitem = fsql.Select().Where(a => a.Id == item.Id).ToOne(); + + var item2 = new test_NumberTypeCrud + { + testFieldSByte = sbyte.MaxValue, + testFieldSByteNullable = sbyte.MinValue, + testFieldShort = short.MaxValue, + testFieldShortNullable = short.MinValue, + testFieldInt = int.MaxValue, + testFieldIntNullable = int.MinValue, + testFieldLong = long.MaxValue, + testFieldLongNullable = long.MinValue, + + testFieldByte = byte.MaxValue, + testFieldByteNullable = byte.MinValue, + testFieldUShort = ushort.MaxValue, + testFieldUShortNullable = ushort.MinValue, + testFieldUInt = uint.MaxValue, + testFieldUIntNullable = uint.MinValue, + testFieldULong = ulong.MaxValue, + testFieldULongNullable = ulong.MinValue, + + testFieldDouble = 888.88, + testFieldDoubleNullable = 222.22, + testFieldFloat = 777.77F, + testFieldFloatNullable = 333.33F, + testFieldDecimal = 999.99M, + testFieldDecimalNullable = 111.11M, + }; + + var sqlText = fsql.Insert(item2).NoneParameter().ToSql(); + Assert.Equal("INSERT INTO \"test_numbertypecrud\"(\"testfieldsbyte\", \"testfieldshort\", \"testfieldint\", \"testfieldlong\", \"testfieldbyte\", \"testfieldushort\", \"testfielduint\", \"testfieldulong\", \"testfielddouble\", \"testfieldfloat\", \"testfielddecimal\", \"testfieldsbytenullable\", \"testfieldshortnullable\", \"testfieldintnullable\", \"testfieldlongnullable\", \"testfieldbytenullable\", \"testfieldushortnullable\", \"testfielduintnullable\", \"testfieldulongnullable\", \"testfielddoublenullable\", \"testfieldfloatnullable\", \"testfielddecimalnullable\") VALUES(127, 32767, 2147483647, 9223372036854775807, 255, 65535, 4294967295, 18446744073709551615, 888.88, 777.77, 999.99, -128, -32768, -2147483648, -9223372036854775808, 0, 0, 0, 0, 222.22, 333.33, 111.11)", sqlText); + item2.Id = (int)fsql.Insert(item2).NoneParameter().ExecuteIdentity(); + var item3NP = fsql.Select().Where(a => a.Id == item2.Id).ToOne(); + Assert.Equal(item3NP.Id, item2.Id); + Assert.Equal(item3NP.testFieldSByte, item2.testFieldSByte); + Assert.Equal(item3NP.testFieldShort, item2.testFieldShort); + Assert.Equal(item3NP.testFieldInt, item2.testFieldInt); + Assert.Equal(item3NP.testFieldLong, item2.testFieldLong); + Assert.Equal(item3NP.testFieldByte, item2.testFieldByte); + Assert.Equal(item3NP.testFieldUShort, item2.testFieldUShort); + Assert.Equal(item3NP.testFieldUInt, item2.testFieldUInt); + Assert.Equal(item3NP.testFieldULong, item2.testFieldULong); + Assert.Equal(item3NP.testFieldDouble, item2.testFieldDouble); + Assert.Equal(item3NP.testFieldFloat, item2.testFieldFloat); + Assert.Equal(item3NP.testFieldDecimal, item2.testFieldDecimal); + + Assert.Equal(item3NP.testFieldSByteNullable, item2.testFieldSByteNullable); + Assert.Equal(item3NP.testFieldShortNullable, item2.testFieldShortNullable); + Assert.Equal(item3NP.testFieldIntNullable, item2.testFieldIntNullable); + Assert.Equal(item3NP.testFieldLongNullable, item2.testFieldLongNullable); + Assert.Equal(item3NP.testFieldByteNullable, item2.testFieldByteNullable); + Assert.Equal(item3NP.testFieldUShortNullable, item2.testFieldUShortNullable); + Assert.Equal(item3NP.testFieldUIntNullable, item2.testFieldUIntNullable); + Assert.Equal(item3NP.testFieldULongNullable, item2.testFieldULongNullable); + Assert.Equal(item3NP.testFieldDoubleNullable, item2.testFieldDoubleNullable); + Assert.Equal(item3NP.testFieldFloatNullable, item2.testFieldFloatNullable); + Assert.Equal(item3NP.testFieldDecimalNullable, item2.testFieldDecimalNullable); + + sqlText = fsql.Insert(item2).ToSql(); + Assert.Equal("INSERT INTO \"test_numbertypecrud\"(\"testfieldsbyte\", \"testfieldshort\", \"testfieldint\", \"testfieldlong\", \"testfieldbyte\", \"testfieldushort\", \"testfielduint\", \"testfieldulong\", \"testfielddouble\", \"testfieldfloat\", \"testfielddecimal\", \"testfieldsbytenullable\", \"testfieldshortnullable\", \"testfieldintnullable\", \"testfieldlongnullable\", \"testfieldbytenullable\", \"testfieldushortnullable\", \"testfielduintnullable\", \"testfieldulongnullable\", \"testfielddoublenullable\", \"testfieldfloatnullable\", \"testfielddecimalnullable\") VALUES(127, 32767, 2147483647, 9223372036854775807, 255, 65535, 4294967295, 18446744073709551615, 888.88, 777.77, 999.99, -128, -32768, -2147483648, -9223372036854775808, 0, 0, 0, 0, 222.22, 333.33, 111.11)", sqlText); + item2.Id = (int)fsql.Insert(item2).ExecuteIdentity(); + item3NP = fsql.Select().Where(a => a.Id == item2.Id).ToOne(); + Assert.Equal(item3NP.Id, item2.Id); + Assert.Equal(item3NP.testFieldSByte, item2.testFieldSByte); + Assert.Equal(item3NP.testFieldShort, item2.testFieldShort); + Assert.Equal(item3NP.testFieldInt, item2.testFieldInt); + Assert.Equal(item3NP.testFieldLong, item2.testFieldLong); + Assert.Equal(item3NP.testFieldByte, item2.testFieldByte); + Assert.Equal(item3NP.testFieldUShort, item2.testFieldUShort); + Assert.Equal(item3NP.testFieldUInt, item2.testFieldUInt); + Assert.Equal(item3NP.testFieldULong, item2.testFieldULong); + Assert.Equal(item3NP.testFieldDouble, item2.testFieldDouble); + Assert.Equal(item3NP.testFieldFloat, item2.testFieldFloat); + Assert.Equal(item3NP.testFieldDecimal, item2.testFieldDecimal); + + Assert.Equal(item3NP.testFieldSByteNullable, item2.testFieldSByteNullable); + Assert.Equal(item3NP.testFieldShortNullable, item2.testFieldShortNullable); + Assert.Equal(item3NP.testFieldIntNullable, item2.testFieldIntNullable); + Assert.Equal(item3NP.testFieldLongNullable, item2.testFieldLongNullable); + Assert.Equal(item3NP.testFieldByteNullable, item2.testFieldByteNullable); + Assert.Equal(item3NP.testFieldUShortNullable, item2.testFieldUShortNullable); + Assert.Equal(item3NP.testFieldUIntNullable, item2.testFieldUIntNullable); + Assert.Equal(item3NP.testFieldULongNullable, item2.testFieldULongNullable); + Assert.Equal(item3NP.testFieldDoubleNullable, item2.testFieldDoubleNullable); + Assert.Equal(item3NP.testFieldFloatNullable, item2.testFieldFloatNullable); + Assert.Equal(item3NP.testFieldDecimalNullable, item2.testFieldDecimalNullable); + + var items = fsql.Select().ToList(); + var itemstb = fsql.Select().ToDataTable(); + } + class test_NumberTypeCrud + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + + public sbyte testFieldSByte { get; set; } + public short testFieldShort { get; set; } + public int testFieldInt { get; set; } + public long testFieldLong { get; set; } + public byte testFieldByte { get; set; } + public ushort testFieldUShort { get; set; } + public uint testFieldUInt { get; set; } + public ulong testFieldULong { get; set; } + public double testFieldDouble { get; set; } + public float testFieldFloat { get; set; } + public decimal testFieldDecimal { get; set; } + + public sbyte? testFieldSByteNullable { get; set; } + public short? testFieldShortNullable { get; set; } + public int? testFieldIntNullable { get; set; } + public long? testFieldLongNullable { get; set; } + public byte? testFieldByteNullable { get; set; } + public ushort? testFieldUShortNullable { get; set; } + public uint? testFieldUIntNullable { get; set; } + public ulong? testFieldULongNullable { get; set; } + public double? testFieldDoubleNullable { get; set; } + public float? testFieldFloatNullable { get; set; } + public decimal? testFieldDecimalNullable { get; set; } + } + + [Fact] + public void NumberArrayTypeCrud() + { + var item = new test_NumberArrayTypeCrud { }; + item.Id = (int)fsql.Insert(item).ExecuteIdentity(); + + var newitem = fsql.Select().Where(a => a.Id == item.Id).ToOne(); + + var item2 = new test_NumberArrayTypeCrud + { + testFieldByteArrayNullable = new byte?[] { 0, 1, 2, 3, null, 4, 5, 6 }, + testFieldShortArray = new short[] { 1, 2, 3, 4, 5 }, + testFieldShortArrayNullable = new short?[] { 1, 2, 3, null, 4, 5 }, + testFieldIntArray = new[] { 1, 2, 3, 4, 5 }, + testFieldIntArrayNullable = new int?[] { 1, 2, 3, null, 4, 5 }, + testFieldLongArray = new long[] { 10, 20, 30, 40, 50 }, + testFieldLongArrayNullable = new long?[] { 500, 600, 700, null, 999, 1000 }, + + testFieldSByteArray = new sbyte[] { 1, 2, 3, 4, 5 }, + testFieldSByteArrayNullable = new sbyte?[] { 1, 2, 3, null, 4, 5 }, + testFieldUShortArray = new ushort[] { 11, 12, 13, 14, 15 }, + testFieldUShortArrayNullable = new ushort?[] { 11, 12, 13, null, 14, 15 }, + testFieldUIntArray = new uint[] { 1, 2, 3, 4, 5 }, + testFieldUIntArrayNullable = new uint?[] { 1, 2, 3, null, 4, 5 }, + testFieldULongArray = new ulong[] { 10, 20, 30, 40, 50 }, + testFieldULongArrayNullable = new ulong?[] { 10, 20, 30, null, 40, 50 }, + + testFieldDoubleArray = new[] { 888.81, 888.82, 888.83 }, + testFieldDoubleArrayNullable = new double?[] { 888.11, 888.12, null, 888.13 }, + testFieldFloatArray = new[] { 777.71F, 777.72F, 777.73F }, + testFieldFloatArrayNullable = new float?[] { 777.71F, 777.72F, null, 777.73F }, + testFieldDecimalArray = new[] { 999.91M, 999.92M, 999.93M }, + testFieldDecimalArrayNullable = new decimal?[] { 998.11M, 998.12M, null, 998.13M }, + }; + + var sqlText = fsql.Insert(item2).NoneParameter().ToSql(); + Assert.Equal("INSERT INTO \"test_numberarraytypecrud\"(\"testfieldsbytearray\", \"testfieldshortarray\", \"testfieldintarray\", \"testfieldlongarray\", \"testfieldushortarray\", \"testfielduintarray\", \"testfieldulongarray\", \"testfielddoublearray\", \"testfieldfloatarray\", \"testfielddecimalarray\", \"testfieldsbytearraynullable\", \"testfieldshortarraynullable\", \"testfieldintarraynullable\", \"testfieldlongarraynullable\", \"testfieldbytearraynullable\", \"testfieldushortarraynullable\", \"testfielduintarraynullable\", \"testfieldulongarraynullable\", \"testfielddoublearraynullable\", \"testfieldfloatarraynullable\", \"testfielddecimalarraynullable\") VALUES([1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [10,20,30,40,50], [11,12,13,14,15], [1,2,3,4,5], [10,20,30,40,50], [888.81,888.82,888.83], [777.71,777.72,777.73], [999.91,999.92,999.93], [1,2,3,0,4,5], [1,2,3,0,4,5], [1,2,3,0,4,5], [500,600,700,0,999,1000], [0,1,2,3,0,4,5,6], [11,12,13,0,14,15], [1,2,3,0,4,5], [10,20,30,0,40,50], [888.11,888.12,0,888.13], [777.71,777.72,0,777.73], [998.11,998.12,0,998.13])", sqlText); + item2.Id = (int)fsql.Insert(item2).NoneParameter().ExecuteIdentity(); + var item3NP = fsql.Select().Where(a => a.Id == item2.Id).ToOne(); + Assert.Equal(item3NP.Id, item2.Id); + Assert.Equal("1, 2, 3, 4, 5", string.Join(", ", item3NP.testFieldSByteArray)); + Assert.Equal("1, 2, 3, 4, 5", string.Join(", ", item3NP.testFieldShortArray)); + Assert.Equal("1, 2, 3, 4, 5", string.Join(", ", item3NP.testFieldIntArray)); + Assert.Equal("10, 20, 30, 40, 50", string.Join(", ", item3NP.testFieldLongArray)); + Assert.Equal("11, 12, 13, 14, 15", string.Join(", ", item3NP.testFieldUShortArray)); + Assert.Equal("1, 2, 3, 4, 5", string.Join(", ", item3NP.testFieldUIntArray)); + Assert.Equal("10, 20, 30, 40, 50", string.Join(", ", item3NP.testFieldULongArray)); + Assert.Equal("888.81, 888.82, 888.83", string.Join(", ", item3NP.testFieldDoubleArray)); + Assert.Equal("777.71, 777.72, 777.73", string.Join(", ", item3NP.testFieldFloatArray)); + Assert.Equal("999.91, 999.92, 999.93", string.Join(", ", item3NP.testFieldDecimalArray)); + + Assert.Equal("1, 2, 3, 0, 4, 5", string.Join(", ", item3NP.testFieldSByteArrayNullable)); + Assert.Equal("1, 2, 3, 0, 4, 5", string.Join(", ", item3NP.testFieldShortArrayNullable)); + Assert.Equal("1, 2, 3, 0, 4, 5", string.Join(", ", item3NP.testFieldIntArrayNullable)); + Assert.Equal("500, 600, 700, 0, 999, 1000", string.Join(", ", item3NP.testFieldLongArrayNullable)); + Assert.Equal("0, 1, 2, 3, 0, 4, 5, 6", string.Join(", ", item3NP.testFieldByteArrayNullable)); + Assert.Equal("11, 12, 13, 0, 14, 15", string.Join(", ", item3NP.testFieldUShortArrayNullable)); + Assert.Equal("1, 2, 3, 0, 4, 5", string.Join(", ", item3NP.testFieldUIntArrayNullable)); + Assert.Equal("10, 20, 30, 0, 40, 50", string.Join(", ", item3NP.testFieldULongArrayNullable)); + Assert.Equal("888.11, 888.12, 0, 888.13", string.Join(", ", item3NP.testFieldDoubleArrayNullable)); + Assert.Equal("777.71, 777.72, 0, 777.73", string.Join(", ", item3NP.testFieldFloatArrayNullable)); + Assert.Equal("998.11, 998.12, 0, 998.13", string.Join(", ", item3NP.testFieldDecimalArrayNullable)); + + sqlText = fsql.Insert(item2).ToSql(); + Assert.Equal("INSERT INTO \"test_numberarraytypecrud\"(\"testfieldsbytearray\", \"testfieldshortarray\", \"testfieldintarray\", \"testfieldlongarray\", \"testfieldushortarray\", \"testfielduintarray\", \"testfieldulongarray\", \"testfielddoublearray\", \"testfieldfloatarray\", \"testfielddecimalarray\", \"testfieldsbytearraynullable\", \"testfieldshortarraynullable\", \"testfieldintarraynullable\", \"testfieldlongarraynullable\", \"testfieldbytearraynullable\", \"testfieldushortarraynullable\", \"testfielduintarraynullable\", \"testfieldulongarraynullable\", \"testfielddoublearraynullable\", \"testfieldfloatarraynullable\", \"testfielddecimalarraynullable\") VALUES([1,2,3,4,5], [1,2,3,4,5], [1,2,3,4,5], [10,20,30,40,50], [11,12,13,14,15], [1,2,3,4,5], [10,20,30,40,50], [888.81,888.82,888.83], [777.71,777.72,777.73], [999.91,999.92,999.93], [1,2,3,0,4,5], [1,2,3,0,4,5], [1,2,3,0,4,5], [500,600,700,0,999,1000], [0,1,2,3,0,4,5,6], [11,12,13,0,14,15], [1,2,3,0,4,5], [10,20,30,0,40,50], [888.11,888.12,0,888.13], [777.71,777.72,0,777.73], [998.11,998.12,0,998.13])", sqlText); + item2.Id = (int)fsql.Insert(item2).ExecuteIdentity(); + item3NP = fsql.Select().Where(a => a.Id == item2.Id).ToOne(); + Assert.Equal(item3NP.Id, item2.Id); + Assert.Equal("1, 2, 3, 4, 5", string.Join(", ", item3NP.testFieldSByteArray)); + Assert.Equal("1, 2, 3, 4, 5", string.Join(", ", item3NP.testFieldShortArray)); + Assert.Equal("1, 2, 3, 4, 5", string.Join(", ", item3NP.testFieldIntArray)); + Assert.Equal("10, 20, 30, 40, 50", string.Join(", ", item3NP.testFieldLongArray)); + Assert.Equal("11, 12, 13, 14, 15", string.Join(", ", item3NP.testFieldUShortArray)); + Assert.Equal("1, 2, 3, 4, 5", string.Join(", ", item3NP.testFieldUIntArray)); + Assert.Equal("10, 20, 30, 40, 50", string.Join(", ", item3NP.testFieldULongArray)); + Assert.Equal("888.81, 888.82, 888.83", string.Join(", ", item3NP.testFieldDoubleArray)); + Assert.Equal("777.71, 777.72, 777.73", string.Join(", ", item3NP.testFieldFloatArray)); + Assert.Equal("999.91, 999.92, 999.93", string.Join(", ", item3NP.testFieldDecimalArray)); + + Assert.Equal("1, 2, 3, 0, 4, 5", string.Join(", ", item3NP.testFieldSByteArrayNullable)); + Assert.Equal("1, 2, 3, 0, 4, 5", string.Join(", ", item3NP.testFieldShortArrayNullable)); + Assert.Equal("1, 2, 3, 0, 4, 5", string.Join(", ", item3NP.testFieldIntArrayNullable)); + Assert.Equal("500, 600, 700, 0, 999, 1000", string.Join(", ", item3NP.testFieldLongArrayNullable)); + Assert.Equal("0, 1, 2, 3, 0, 4, 5, 6", string.Join(", ", item3NP.testFieldByteArrayNullable)); + Assert.Equal("11, 12, 13, 0, 14, 15", string.Join(", ", item3NP.testFieldUShortArrayNullable)); + Assert.Equal("1, 2, 3, 0, 4, 5", string.Join(", ", item3NP.testFieldUIntArrayNullable)); + Assert.Equal("10, 20, 30, 0, 40, 50", string.Join(", ", item3NP.testFieldULongArrayNullable)); + Assert.Equal("888.11, 888.12, 0, 888.13", string.Join(", ", item3NP.testFieldDoubleArrayNullable)); + Assert.Equal("777.71, 777.72, 0, 777.73", string.Join(", ", item3NP.testFieldFloatArrayNullable)); + Assert.Equal("998.11, 998.12, 0, 998.13", string.Join(", ", item3NP.testFieldDecimalArrayNullable)); + + var items = fsql.Select().ToList(); + var itemstb = fsql.Select().ToDataTable(); + } + class test_NumberArrayTypeCrud + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + + public sbyte[] testFieldSByteArray { get; set; } + public short[] testFieldShortArray { get; set; } + public int[] testFieldIntArray { get; set; } + public long[] testFieldLongArray { get; set; } + public ushort[] testFieldUShortArray { get; set; } + public uint[] testFieldUIntArray { get; set; } + public ulong[] testFieldULongArray { get; set; } + public double[] testFieldDoubleArray { get; set; } + public float[] testFieldFloatArray { get; set; } + public decimal[] testFieldDecimalArray { get; set; } + + public sbyte?[] testFieldSByteArrayNullable { get; set; } + public short?[] testFieldShortArrayNullable { get; set; } + public int?[] testFieldIntArrayNullable { get; set; } + public long?[] testFieldLongArrayNullable { get; set; } + public byte?[] testFieldByteArrayNullable { get; set; } + public ushort?[] testFieldUShortArrayNullable { get; set; } + public uint?[] testFieldUIntArrayNullable { get; set; } + public ulong?[] testFieldULongArrayNullable { get; set; } + public double?[] testFieldDoubleArrayNullable { get; set; } + public float?[] testFieldFloatArrayNullable { get; set; } + public decimal?[] testFieldDecimalArrayNullable { get; set; } + } + + [Fact] + public void OtherTypeCrud() + { + var item = new test_OtherTypeCrud { }; + item.Id = (int)fsql.Insert(item).ExecuteIdentity(); + + var newitem = fsql.Select().Where(a => a.Id == item.Id).ToOne(); + + var newGuid = Guid.Parse("9e461804-7ed6-4a66-a609-408b2c195abf"); + var item2 = new test_OtherTypeCrud + { + testFieldBool = true, + testFieldBoolNullable = true, + testFieldGuid = newGuid, + testFieldGuidNullable = newGuid, + testFieldBytes = Encoding.UTF8.GetBytes("我是中国人"), + testFieldString = "我是中国人string'\\?!@#$%^&*()_+{}}{~?><<>", + testFieldChar = 'X', + testFieldBitArray = new BitArray(Encoding.UTF8.GetBytes("我是")), + + testFieldEnum1 = TableAllTypeEnumType1.e3, + testFieldEnum1Nullable = TableAllTypeEnumType1.e2, + testFieldEnum2 = TableAllTypeEnumType2.f2, + testFieldEnum2Nullable = TableAllTypeEnumType2.f3, + }; + + var sqlText = fsql.Insert(item2).NoneParameter().ToSql(); + Assert.Equal("INSERT INTO \"test_othertypecrud\"(\"testfieldbool\", \"testfieldguid\", \"testfieldbytes\", \"testfieldstring\", \"testfieldchar\", \"testfieldbitarray\", \"testfieldboolnullable\", \"testfieldguidnullable\", \"testfieldenum1\", \"testfieldenum1nullable\", \"testfieldenum2\", \"testfieldenum2nullable\") VALUES(true, '9e461804-7ed6-4a66-a609-408b2c195abf', '\\xE6\\x88\\x91\\xE6\\x98\\xAF\\xE4\\xB8\\xAD\\xE5\\x9B\\xBD\\xE4\\xBA\\xBA'::blob, '我是中国人string''\\?!@#$%^&*()_+{}}{~?><<>', 'X', bit '011001110001000110001001011001110001100111110101', true, '9e461804-7ed6-4a66-a609-408b2c195abf', 2, 1, 1, 2)", sqlText); + item2.Id = (int)fsql.Insert(item2).NoneParameter().ExecuteIdentity(); + var item3NP = fsql.Select().Where(a => a.Id == item2.Id).ToOne(); + Assert.Equal(item3NP.Id, item2.Id); + Assert.Equal(item3NP.testFieldBool, item2.testFieldBool); + Assert.Equal(item3NP.testFieldGuid, item2.testFieldGuid); + Assert.Equal(Convert.ToBase64String(item3NP.testFieldBytes), Convert.ToBase64String(item2.testFieldBytes)); + Assert.Equal(item3NP.testFieldString, item2.testFieldString); + Assert.Equal(item3NP.testFieldChar, item2.testFieldChar); + Assert.Equal(Get1010(item3NP.testFieldBitArray), Get1010(item2.testFieldBitArray)); + + Assert.Equal(item3NP.testFieldBoolNullable, item2.testFieldBoolNullable); + Assert.Equal(item3NP.testFieldGuidNullable, item2.testFieldGuidNullable); + + Assert.Equal(item3NP.testFieldEnum1, item2.testFieldEnum1); + Assert.Equal(item3NP.testFieldEnum1Nullable, item2.testFieldEnum1Nullable); + Assert.Equal(item3NP.testFieldEnum2, item2.testFieldEnum2); + Assert.Equal(item3NP.testFieldEnum2Nullable, item2.testFieldEnum2Nullable); + + sqlText = fsql.Insert(item2).ToSql(); + Assert.Equal("INSERT INTO \"test_othertypecrud\"(\"testfieldbool\", \"testfieldguid\", \"testfieldbytes\", \"testfieldstring\", \"testfieldchar\", \"testfieldbitarray\", \"testfieldboolnullable\", \"testfieldguidnullable\", \"testfieldenum1\", \"testfieldenum1nullable\", \"testfieldenum2\", \"testfieldenum2nullable\") VALUES(true, '9e461804-7ed6-4a66-a609-408b2c195abf', '\\xE6\\x88\\x91\\xE6\\x98\\xAF\\xE4\\xB8\\xAD\\xE5\\x9B\\xBD\\xE4\\xBA\\xBA'::blob, '我是中国人string''\\?!@#$%^&*()_+{}}{~?><<>', 'X', bit '011001110001000110001001011001110001100111110101', true, '9e461804-7ed6-4a66-a609-408b2c195abf', 2, 1, 1, 2)", sqlText); + item2.Id = (int)fsql.Insert(item2).ExecuteIdentity(); + item3NP = fsql.Select().Where(a => a.Id == item2.Id).ToOne(); + Assert.Equal(item3NP.Id, item2.Id); + Assert.Equal(item3NP.testFieldBool, item2.testFieldBool); + Assert.Equal(item3NP.testFieldGuid, item2.testFieldGuid); + Assert.Equal(Convert.ToBase64String(item3NP.testFieldBytes), Convert.ToBase64String(item2.testFieldBytes)); + Assert.Equal(item3NP.testFieldString, item2.testFieldString); + Assert.Equal(item3NP.testFieldChar, item2.testFieldChar); + Assert.Equal(Get1010(item3NP.testFieldBitArray), Get1010(item2.testFieldBitArray)); + + Assert.Equal(item3NP.testFieldBoolNullable, item2.testFieldBoolNullable); + Assert.Equal(item3NP.testFieldGuidNullable, item2.testFieldGuidNullable); + + Assert.Equal(item3NP.testFieldEnum1, item2.testFieldEnum1); + Assert.Equal(item3NP.testFieldEnum1Nullable, item2.testFieldEnum1Nullable); + Assert.Equal(item3NP.testFieldEnum2, item2.testFieldEnum2); + Assert.Equal(item3NP.testFieldEnum2Nullable, item2.testFieldEnum2Nullable); + + var items = fsql.Select().ToList(); + var itemstb = fsql.Select().ToDataTable(); + } + string Get1010(BitArray ba) + { + char[] ba1010 = new char[ba.Length]; + for (int a = 0; a < ba.Length; a++) ba1010[a] = ba[a] ? '1' : '0'; + return new string(ba1010); + } + class test_OtherTypeCrud + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + + public bool testFieldBool { get; set; } + public Guid testFieldGuid { get; set; } + public byte[] testFieldBytes { get; set; } + public string testFieldString { get; set; } + public char testFieldChar { get; set; } + public BitArray testFieldBitArray { get; set; } + + public bool? testFieldBoolNullable { get; set; } + public Guid? testFieldGuidNullable { get; set; } + + public TableAllTypeEnumType1 testFieldEnum1 { get; set; } + public TableAllTypeEnumType1? testFieldEnum1Nullable { get; set; } + public TableAllTypeEnumType2 testFieldEnum2 { get; set; } + public TableAllTypeEnumType2? testFieldEnum2Nullable { get; set; } + } + + [Fact] + public void OtherArrayTypeCrud() + { + var item = new test_OtherArrayTypeCrud { }; + item.Id = (int)fsql.Insert(item).ExecuteIdentity(); + + var newitem = fsql.Select().Where(a => a.Id == item.Id).ToOne(); + + var newGuid = Guid.Parse("9e461804-7ed6-4a66-a609-408b2c195abf"); + var item2 = new test_OtherArrayTypeCrud + { + testFieldBoolArray = new[] { true, true, false, false }, + testFieldBoolArrayNullable = new bool?[] { true, true, null, false, false }, + testFieldBytesArray = new[] { Encoding.UTF8.GetBytes("我是中国人"), Encoding.UTF8.GetBytes("我是中国人") }, + testFieldGuidArray = new[] { newGuid, newGuid }, + testFieldGuidArrayNullable = new Guid?[] { newGuid, null, newGuid }, + testFieldStringArray = new[] { "我是中国人String1", "我是中国人String2", null, "我是中国人String3" }, + testFieldBitArrayArray = new[] { new BitArray(Encoding.UTF8.GetBytes("中国")), new BitArray(Encoding.UTF8.GetBytes("公民")) }, + + testFieldEnum1Array = new[] { TableAllTypeEnumType1.e5, TableAllTypeEnumType1.e2, TableAllTypeEnumType1.e1 }, + testFieldEnum1ArrayNullable = new TableAllTypeEnumType1?[] { TableAllTypeEnumType1.e5, TableAllTypeEnumType1.e2, null, TableAllTypeEnumType1.e1 }, + testFieldEnum2Array = new[] { TableAllTypeEnumType2.f3, TableAllTypeEnumType2.f1 }, + testFieldEnum2ArrayNullable = new TableAllTypeEnumType2?[] { TableAllTypeEnumType2.f3, null, TableAllTypeEnumType2.f1 }, + }; + + var sqlText = fsql.Insert(item2).NoneParameter().ToSql(); + Assert.Equal("INSERT INTO \"test_otherarraytypecrud\"(\"testfieldboolarray\", \"testfieldbytesarray\", \"testfieldstringarray\", \"testfieldguidarray\", \"testfieldboolarraynullable\", \"testfieldguidarraynullable\", \"testfieldbitarrayarray\", \"testfieldenum1array\", \"testfieldenum1arraynullable\", \"testfieldenum2array\", \"testfieldenum2arraynullable\") VALUES([true,true,false,false], ['\\xE6\\x88\\x91\\xE6\\x98\\xAF\\xE4\\xB8\\xAD\\xE5\\x9B\\xBD\\xE4\\xBA\\xBA'::blob,'\\xE6\\x88\\x91\\xE6\\x98\\xAF\\xE4\\xB8\\xAD\\xE5\\x9B\\xBD\\xE4\\xBA\\xBA'::blob], ['我是中国人String1','我是中国人String2',NULL,'我是中国人String3'], ['9e461804-7ed6-4a66-a609-408b2c195abf','9e461804-7ed6-4a66-a609-408b2c195abf'], [true,true,false,false,false], ['9e461804-7ed6-4a66-a609-408b2c195abf','00000000-0000-0000-0000-000000000000','9e461804-7ed6-4a66-a609-408b2c195abf'], [bit '001001110001110110110101101001111101100110111101',bit '101001111010000100110101011001110000110110001001'], [3,1,0], [3,1,0,0], [2,0], [2,0,0])", sqlText); + item2.Id = (int)fsql.Insert(item2).NoneParameter().ExecuteIdentity(); + var item3NP = fsql.Select().Where(a => a.Id == item2.Id).ToOne(); + Assert.Equal(item3NP.Id, item2.Id); + Assert.Equal("True, True, False, False", string.Join(", ", item3NP.testFieldBoolArray)); + Assert.Equal("True, True, False, False, False", string.Join(", ", item3NP.testFieldBoolArrayNullable)); + Assert.Equal("5oiR5piv5Lit5Zu95Lq6, 5oiR5piv5Lit5Zu95Lq6", string.Join(", ", item3NP.testFieldBytesArray.Select(a => Convert.ToBase64String(a)))); + Assert.Equal("9e461804-7ed6-4a66-a609-408b2c195abf, 9e461804-7ed6-4a66-a609-408b2c195abf", string.Join(", ", item3NP.testFieldGuidArray)); + Assert.Equal("9e461804-7ed6-4a66-a609-408b2c195abf, 00000000-0000-0000-0000-000000000000, 9e461804-7ed6-4a66-a609-408b2c195abf", string.Join(", ", item3NP.testFieldGuidArrayNullable)); + Assert.Equal("我是中国人String1, 我是中国人String2, , 我是中国人String3", string.Join(", ", item3NP.testFieldStringArray)); + Assert.Equal("001001110001110110110101101001111101100110111101, 101001111010000100110101011001110000110110001001", string.Join(", ", item3NP.testFieldBitArrayArray.Select(a => Get1010(a)))); + + Assert.Equal("e5, e2, e1", string.Join(", ", item3NP.testFieldEnum1Array)); + Assert.Equal("e5, e2, e1, e1", string.Join(", ", item3NP.testFieldEnum1ArrayNullable)); + Assert.Equal("f3, f1", string.Join(", ", item3NP.testFieldEnum2Array)); + Assert.Equal("f3, f1, f1", string.Join(", ", item3NP.testFieldEnum2ArrayNullable)); + + sqlText = fsql.Insert(item2).ToSql(); + Assert.Equal("INSERT INTO \"test_otherarraytypecrud\"(\"testfieldboolarray\", \"testfieldbytesarray\", \"testfieldstringarray\", \"testfieldguidarray\", \"testfieldboolarraynullable\", \"testfieldguidarraynullable\", \"testfieldbitarrayarray\", \"testfieldenum1array\", \"testfieldenum1arraynullable\", \"testfieldenum2array\", \"testfieldenum2arraynullable\") VALUES([true,true,false,false], ['\\xE6\\x88\\x91\\xE6\\x98\\xAF\\xE4\\xB8\\xAD\\xE5\\x9B\\xBD\\xE4\\xBA\\xBA'::blob,'\\xE6\\x88\\x91\\xE6\\x98\\xAF\\xE4\\xB8\\xAD\\xE5\\x9B\\xBD\\xE4\\xBA\\xBA'::blob], ['我是中国人String1','我是中国人String2',NULL,'我是中国人String3'], ['9e461804-7ed6-4a66-a609-408b2c195abf','9e461804-7ed6-4a66-a609-408b2c195abf'], [true,true,false,false,false], ['9e461804-7ed6-4a66-a609-408b2c195abf','00000000-0000-0000-0000-000000000000','9e461804-7ed6-4a66-a609-408b2c195abf'], [bit '001001110001110110110101101001111101100110111101',bit '101001111010000100110101011001110000110110001001'], [3,1,0], [3,1,0,0], [2,0], [2,0,0])", sqlText); + item2.Id = (int)fsql.Insert(item2).ExecuteIdentity(); + item3NP = fsql.Select().Where(a => a.Id == item2.Id).ToOne(); + Assert.Equal(item3NP.Id, item2.Id); + Assert.Equal("True, True, False, False", string.Join(", ", item3NP.testFieldBoolArray)); + Assert.Equal("True, True, False, False, False", string.Join(", ", item3NP.testFieldBoolArrayNullable)); + Assert.Equal("5oiR5piv5Lit5Zu95Lq6, 5oiR5piv5Lit5Zu95Lq6", string.Join(", ", item3NP.testFieldBytesArray.Select(a => Convert.ToBase64String(a)))); + Assert.Equal("9e461804-7ed6-4a66-a609-408b2c195abf, 9e461804-7ed6-4a66-a609-408b2c195abf", string.Join(", ", item3NP.testFieldGuidArray)); + Assert.Equal("9e461804-7ed6-4a66-a609-408b2c195abf, 00000000-0000-0000-0000-000000000000, 9e461804-7ed6-4a66-a609-408b2c195abf", string.Join(", ", item3NP.testFieldGuidArrayNullable)); + Assert.Equal("我是中国人String1, 我是中国人String2, , 我是中国人String3", string.Join(", ", item3NP.testFieldStringArray)); + Assert.Equal("001001110001110110110101101001111101100110111101, 101001111010000100110101011001110000110110001001", string.Join(", ", item3NP.testFieldBitArrayArray.Select(a => Get1010(a)))); + + Assert.Equal("e5, e2, e1", string.Join(", ", item3NP.testFieldEnum1Array)); + Assert.Equal("e5, e2, e1, e1", string.Join(", ", item3NP.testFieldEnum1ArrayNullable)); + Assert.Equal("f3, f1", string.Join(", ", item3NP.testFieldEnum2Array)); + Assert.Equal("f3, f1, f1", string.Join(", ", item3NP.testFieldEnum2ArrayNullable)); + + var items = fsql.Select().ToList(); + var itemstb = fsql.Select().ToDataTable(); + } + class test_OtherArrayTypeCrud + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + + public bool[] testFieldBoolArray { get; set; } + public byte[][] testFieldBytesArray { get; set; } + public string[] testFieldStringArray { get; set; } + public Guid[] testFieldGuidArray { get; set; } + + public bool?[] testFieldBoolArrayNullable { get; set; } + public Guid?[] testFieldGuidArrayNullable { get; set; } + + public BitArray[] testFieldBitArrayArray { get; set; } + + public TableAllTypeEnumType1[] testFieldEnum1Array { get; set; } + public TableAllTypeEnumType1?[] testFieldEnum1ArrayNullable { get; set; } + public TableAllTypeEnumType2[] testFieldEnum2Array { get; set; } + public TableAllTypeEnumType2?[] testFieldEnum2ArrayNullable { get; set; } + } + IInsert insert => fsql.Insert(); ISelect select => fsql.Select(); @@ -130,6 +642,7 @@ class tuint256tb_01 public void CurdAllField() { var sql1 = select.Where(a => a.testFieldIntArray.Contains(1)).ToSql(); + Assert.Equal(sql1, ""); var lst1 = select.Where(a => a.testFieldIntArray.Contains(1)).ToList(); var item = new TableAllType { }; @@ -226,9 +739,8 @@ public void CurdAllField() testFielLongNullable = long.MinValue }; - var sqlPar = insert.AppendData(item2).ToSql(); - var sqlText = insert.AppendData(item2).NoneParameter().ToSql(); - var item3NP = insert.AppendData(item2).NoneParameter().ExecuteInserted(); + var sqlText = insert.AppendData(item2).ToSql(); + var item3NP = insert.AppendData(item2).ExecuteInserted(); var item3 = insert.AppendData(item2).ExecuteInserted().First(); var newitem2 = select.Where(a => a.Id == item3.Id).ToOne(); diff --git a/FreeSql/Internal/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs index 95f4274e5..01a688f80 100644 --- a/FreeSql/Internal/UtilsExpressionTree.cs +++ b/FreeSql/Internal/UtilsExpressionTree.cs @@ -9,6 +9,7 @@ using System.Data; using System.Data.Common; using System.Globalization; +using System.IO; using System.Linq; using System.Linq.Expressions; using System.Numerics; @@ -2172,6 +2173,20 @@ public static BitArray StringToBitArray(string str1010) for (int a = 0; a < str1010.Length; a++) ret[a] = str1010[a] == '1'; return ret; } + public static byte[] StreamToBytes(Stream stream) + { + var ms = new MemoryStream(); + try + { + stream.CopyTo(ms); + return ms.ToArray(); + } + finally + { + ms.Close(); + ms.Dispose(); + } + } public static TElement[] ListOrArrayToArray(object listOrArray) { if (listOrArray is TElement[] arr2) return arr2; @@ -2196,40 +2211,96 @@ public static TElement[] ListOrArrayToArray(object listOrArray) public static List ListOrArrayToList(object listOrArray) => ListOrArrayToArray(listOrArray)?.ToList(); static ConcurrentDictionary>> _dicGetDataReaderValue = new ConcurrentDictionary>>(); - static MethodInfo MethodGuidTryParse = typeof(Guid).GetMethod("TryParse", new[] { typeof(string), typeof(Guid).MakeByRefType() }); - static MethodInfo MethodEnumParse = typeof(Enum).GetMethod("Parse", new[] { typeof(Type), typeof(string), typeof(bool) }); - static MethodInfo MethodConvertChangeType = typeof(Convert).GetMethod("ChangeType", new[] { typeof(object), typeof(Type) }); - static MethodInfo MethodTimeSpanFromSeconds = typeof(TimeSpan).GetMethod("FromSeconds", new[] { typeof(double) } ); - static MethodInfo MethodSByteTryParse = typeof(sbyte).GetMethod("TryParse", new[] { typeof(string), typeof(sbyte).MakeByRefType() }); - static MethodInfo MethodShortTryParse = typeof(short).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(short).MakeByRefType() }); - static MethodInfo MethodIntTryParse = typeof(int).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(int).MakeByRefType() }); - static MethodInfo MethodLongTryParse = typeof(long).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(long).MakeByRefType() }); - static MethodInfo MethodByteTryParse = typeof(byte).GetMethod("TryParse", new[] { typeof(string), typeof(byte).MakeByRefType() }); - static MethodInfo MethodUShortTryParse = typeof(ushort).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(ushort).MakeByRefType() }); - static MethodInfo MethodUIntTryParse = typeof(uint).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(uint).MakeByRefType() }); - static MethodInfo MethodULongTryParse = typeof(ulong).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(ulong).MakeByRefType() }); - static MethodInfo MethodDoubleTryParse = typeof(double).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(double).MakeByRefType() }); - static MethodInfo MethodFloatTryParse = typeof(float).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(float).MakeByRefType() }); - static MethodInfo MethodDecimalTryParse = typeof(decimal).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(decimal).MakeByRefType() }); - static MethodInfo MethodTimeSpanTryParse = typeof(TimeSpan).GetMethod("TryParse", new[] { typeof(string), typeof(TimeSpan).MakeByRefType() }); - static MethodInfo MethodDateTimeTryParse = typeof(DateTime).GetMethod("TryParse", new[] { typeof(string), typeof(DateTime).MakeByRefType() }); - static MethodInfo MethodDateTimeOffsetTryParse = typeof(DateTimeOffset).GetMethod("TryParse", new[] { typeof(string), typeof(DateTimeOffset).MakeByRefType() }); - static MethodInfo MethodToString = typeof(Utils).GetMethod("ToStringConcat", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(object) }, null); - static MethodInfo MethodValueIsEnumAndTargetIsNumber = typeof(Utils).GetMethod("ValueIsEnumAndTargetIsNumber", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(object), typeof(Type) }, null); - static MethodInfo MethodBigIntegerParse = typeof(Utils).GetMethod("ToBigInteger", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null); - static PropertyInfo PropertyDateTimeOffsetDateTime = typeof(DateTimeOffset).GetProperty("DateTime", BindingFlags.Instance | BindingFlags.Public); - static PropertyInfo PropertyDateTimeTicks = typeof(DateTime).GetProperty("Ticks", BindingFlags.Instance | BindingFlags.Public); - static ConstructorInfo CtorDateTimeOffsetArgsTicks = typeof(DateTimeOffset).GetConstructor(new[] { typeof(long), typeof(TimeSpan) }); + static MethodInfo MethodGuidTryParse => LazyManager.MethodGuidTryParse.Value; + static MethodInfo MethodEnumParse => LazyManager.MethodEnumParse.Value; + static MethodInfo MethodConvertChangeType => LazyManager.MethodConvertChangeType.Value; + static MethodInfo MethodTimeSpanFromSeconds => LazyManager.MethodTimeSpanFromSeconds.Value; + static MethodInfo MethodSByteTryParse => LazyManager.MethodSByteTryParse.Value; + static MethodInfo MethodShortTryParse => LazyManager.MethodShortTryParse.Value; + static MethodInfo MethodIntTryParse => LazyManager.MethodIntTryParse.Value; + static MethodInfo MethodLongTryParse => LazyManager.MethodLongTryParse.Value; + static MethodInfo MethodByteTryParse => LazyManager.MethodByteTryParse.Value; + static MethodInfo MethodUShortTryParse => LazyManager.MethodUShortTryParse.Value; + static MethodInfo MethodUIntTryParse => LazyManager.MethodUIntTryParse.Value; + static MethodInfo MethodULongTryParse => LazyManager.MethodULongTryParse.Value; + static MethodInfo MethodDoubleTryParse => LazyManager.MethodDoubleTryParse.Value; + static MethodInfo MethodFloatTryParse => LazyManager.MethodFloatTryParse.Value; + static MethodInfo MethodDecimalTryParse => LazyManager.MethodDecimalTryParse.Value; + static MethodInfo MethodTimeSpanTryParse => LazyManager.MethodTimeSpanTryParse.Value; + static MethodInfo MethodDateTimeTryParse => LazyManager.MethodDateTimeTryParse.Value; + static MethodInfo MethodDateTimeOffsetTryParse => LazyManager.MethodDateTimeOffsetTryParse.Value; + static MethodInfo MethodToString => LazyManager.MethodToString.Value; + static MethodInfo MethodBigIntegerParse => LazyManager.MethodBigIntegerParse.Value; + static PropertyInfo PropertyDateTimeOffsetDateTime => LazyManager.PropertyDateTimeOffsetDateTime.Value; + static PropertyInfo PropertyDateTimeTicks => LazyManager.PropertyDateTimeTicks.Value; + static ConstructorInfo CtorDateTimeOffsetArgsTicks => LazyManager.CtorDateTimeOffsetArgsTicks.Value; static Encoding DefaultEncoding = Encoding.UTF8; - static MethodInfo MethodEncodingGetBytes = typeof(Encoding).GetMethod("GetBytes", new[] { typeof(string) }); - static MethodInfo MethodEncodingGetString = typeof(Encoding).GetMethod("GetString", new[] { typeof(byte[]) }); - static MethodInfo MethodStringToCharArray = typeof(string).GetMethod("ToCharArray", new Type[0]); - static MethodInfo MethodStringToChar = typeof(Utils).GetMethod("StringToChar", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null); - static MethodInfo MethodStringToBitArray = typeof(Utils).GetMethod("StringToBitArray", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null); - static MethodInfo MethodGuidToBytes = typeof(Utils).GetMethod("GuidToBytes", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(Guid) }, null); - static MethodInfo MethodBytesToGuid = typeof(Utils).GetMethod("BytesToGuid", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(byte[]) }, null); - static MethodInfo MethodListOrArrayToArray = typeof(Utils).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(a => a.Name == "ListOrArrayToArray").FirstOrDefault(); - static MethodInfo MethodListOrArrayToList = typeof(Utils).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(a => a.Name == "ListOrArrayToList").FirstOrDefault(); + + static class LazyManager + { + internal static Lazy MethodGuidTryParse = new Lazy(() => typeof(Guid).GetMethod("TryParse", new[] { typeof(string), typeof(Guid).MakeByRefType() })); + internal static Lazy MethodEnumParse = new Lazy(() => typeof(Enum).GetMethod("Parse", new[] { typeof(Type), typeof(string), typeof(bool) })); + internal static Lazy MethodConvertChangeType = new Lazy(() => typeof(Convert).GetMethod("ChangeType", new[] { typeof(object), typeof(Type) })); + internal static Lazy MethodTimeSpanFromSeconds = new Lazy(() => typeof(TimeSpan).GetMethod("FromSeconds", new[] { typeof(double) })); + internal static Lazy MethodSByteTryParse = new Lazy(() => typeof(sbyte).GetMethod("TryParse", new[] { typeof(string), typeof(sbyte).MakeByRefType() })); + internal static Lazy MethodShortTryParse = new Lazy(() => typeof(short).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(short).MakeByRefType() })); + internal static Lazy MethodIntTryParse = new Lazy(() => typeof(int).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(int).MakeByRefType() })); + internal static Lazy MethodLongTryParse = new Lazy(() => typeof(long).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(long).MakeByRefType() })); + internal static Lazy MethodByteTryParse = new Lazy(() => typeof(byte).GetMethod("TryParse", new[] { typeof(string), typeof(byte).MakeByRefType() })); + internal static Lazy MethodUShortTryParse = new Lazy(() => typeof(ushort).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(ushort).MakeByRefType() })); + internal static Lazy MethodUIntTryParse = new Lazy(() => typeof(uint).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(uint).MakeByRefType() })); + internal static Lazy MethodULongTryParse = new Lazy(() => typeof(ulong).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(ulong).MakeByRefType() })); + internal static Lazy MethodDoubleTryParse = new Lazy(() => typeof(double).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(double).MakeByRefType() })); + internal static Lazy MethodFloatTryParse = new Lazy(() => typeof(float).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(float).MakeByRefType() })); + internal static Lazy MethodDecimalTryParse = new Lazy(() => typeof(decimal).GetMethod("TryParse", new[] { typeof(string), typeof(System.Globalization.NumberStyles), typeof(IFormatProvider), typeof(decimal).MakeByRefType() })); + internal static Lazy MethodTimeSpanTryParse = new Lazy(() => typeof(TimeSpan).GetMethod("TryParse", new[] { typeof(string), typeof(TimeSpan).MakeByRefType() })); + internal static Lazy MethodDateTimeTryParse = new Lazy(() => typeof(DateTime).GetMethod("TryParse", new[] { typeof(string), typeof(DateTime).MakeByRefType() })); + internal static Lazy MethodDateTimeOffsetTryParse = new Lazy(() => typeof(DateTimeOffset).GetMethod("TryParse", new[] { typeof(string), typeof(DateTimeOffset).MakeByRefType() })); + internal static Lazy MethodToString = new Lazy(() => typeof(Utils).GetMethod("ToStringConcat", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(object) }, null)); + internal static Lazy MethodBigIntegerParse = new Lazy(() => typeof(Utils).GetMethod("ToBigInteger", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null)); + internal static Lazy PropertyDateTimeOffsetDateTime = new Lazy(() => typeof(DateTimeOffset).GetProperty("DateTime", BindingFlags.Instance | BindingFlags.Public)); + internal static Lazy PropertyDateTimeTicks = new Lazy(() => typeof(DateTime).GetProperty("Ticks", BindingFlags.Instance | BindingFlags.Public)); + internal static Lazy CtorDateTimeOffsetArgsTicks = new Lazy(() => typeof(DateTimeOffset).GetConstructor(new[] { typeof(long), typeof(TimeSpan) })); + + internal static Lazy MethodValueIsEnumAndTargetIsNumber = new Lazy(() => typeof(Utils).GetMethod("ValueIsEnumAndTargetIsNumber", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(object), typeof(Type) }, null)); + internal static Lazy MethodEncodingGetBytes = new Lazy(() => typeof(Encoding).GetMethod("GetBytes", new[] { typeof(string) })); + internal static Lazy MethodEncodingGetString = new Lazy(() => typeof(Encoding).GetMethod("GetString", new[] { typeof(byte[]) })); + internal static Lazy MethodStringToCharArray = new Lazy(() => typeof(string).GetMethod("ToCharArray", new Type[0])); + internal static Lazy MethodStringToChar = new Lazy(() => typeof(Utils).GetMethod("StringToChar", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null)); + internal static Lazy MethodStringToBitArray = new Lazy(() => typeof(Utils).GetMethod("StringToBitArray", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null)); + internal static Lazy MethodGuidToBytes = new Lazy(() => typeof(Utils).GetMethod("GuidToBytes", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(Guid) }, null)); + internal static Lazy MethodBytesToGuid = new Lazy(() => typeof(Utils).GetMethod("BytesToGuid", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(byte[]) }, null)); + internal static Lazy MethodStreamToBytes = new Lazy(() => typeof(Utils).GetMethod("StreamToBytes", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(Stream) }, null)); + internal static Lazy MethodListOrArrayToArray = new Lazy(() => typeof(Utils).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(a => a.Name == "ListOrArrayToArray").FirstOrDefault()); + internal static Lazy MethodListOrArrayToList = new Lazy(() => typeof(Utils).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(a => a.Name == "ListOrArrayToList").FirstOrDefault()); + internal static Lazy TypeTimeOnly = new Lazy(() => Type.GetType("System.TimeOnly")); + internal static Lazy MethodTimeOnlyToTimeSpan = new Lazy(() => TypeTimeOnly.Value.GetMethod("ToTimeSpan")); + internal static Lazy MethodTimeOnlyFromTimeSpan = new Lazy(() => TypeTimeOnly.Value.GetMethod("FromTimeSpan", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(TimeSpan) }, null)); + internal static Lazy MethodTimeOnlyParse = new Lazy(() => TypeTimeOnly.Value.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string) }, null)); + internal static Lazy TypeDateOnly = new Lazy(() => Type.GetType("System.DateOnly")); + internal static Lazy MethodDateOnlyToDateTime = new Lazy(() => TypeDateOnly.Value.GetMethod("ToDateTime", BindingFlags.Instance | BindingFlags.Public, null, new[] { TypeTimeOnly.Value }, null)); + internal static Lazy MethodDateOnlyFromDateTime = new Lazy(() => TypeDateOnly.Value.GetMethod("FromDateTime", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(DateTime) }, null)); + internal static Lazy MethodDateOnlyParse = new Lazy(() => TypeDateOnly.Value.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string) }, null)); + } + static MethodInfo MethodValueIsEnumAndTargetIsNumber => LazyManager.MethodValueIsEnumAndTargetIsNumber.Value; + static MethodInfo MethodEncodingGetBytes => LazyManager.MethodEncodingGetBytes.Value; + static MethodInfo MethodEncodingGetString => LazyManager.MethodEncodingGetString.Value; + static MethodInfo MethodStringToCharArray => LazyManager.MethodStringToCharArray.Value; + static MethodInfo MethodStringToChar => LazyManager.MethodStringToChar.Value; + static MethodInfo MethodStringToBitArray => LazyManager.MethodStringToBitArray.Value; + static MethodInfo MethodGuidToBytes => LazyManager.MethodGuidToBytes.Value; + static MethodInfo MethodBytesToGuid => LazyManager.MethodBytesToGuid.Value; + static MethodInfo MethodStreamToBytes => LazyManager.MethodStreamToBytes.Value; + static MethodInfo MethodListOrArrayToArray=> LazyManager.MethodListOrArrayToArray.Value; + static MethodInfo MethodListOrArrayToList => LazyManager.MethodListOrArrayToList.Value; + static Type TypeTimeOnly => LazyManager.TypeTimeOnly.Value; + static MethodInfo MethodTimeOnlyToTimeSpan => LazyManager.MethodTimeOnlyToTimeSpan.Value; + static MethodInfo MethodTimeOnlyFromTimeSpan => LazyManager.MethodTimeOnlyFromTimeSpan.Value; + static MethodInfo MethodTimeOnlyParse => LazyManager.MethodTimeOnlyParse.Value; + static Type TypeDateOnly => LazyManager.TypeDateOnly.Value; + static MethodInfo MethodDateOnlyToDateTime => LazyManager.MethodDateOnlyToDateTime.Value; + static MethodInfo MethodDateOnlyFromDateTime => LazyManager.MethodDateOnlyFromDateTime.Value; + static MethodInfo MethodDateOnlyParse => LazyManager.MethodDateOnlyParse.Value; public static ConcurrentDictionary TypeHandlers { get; } = new ConcurrentDictionary(); @@ -2259,7 +2330,11 @@ Expression LocalFuncGetExpression(bool ignoreArray = false) Expression.IfThenElse( Expression.OrElse(Expression.TypeEqual(valueExp, typeof(Guid)), Expression.TypeEqual(valueExp, typeof(Guid?))), Expression.Return(returnTarget, Expression.Call(MethodGuidToBytes, Expression.Convert(valueExp, typeof(Guid)))), - callToBytesExp + Expression.IfThenElse( + Expression.TypeIs(valueExp, typeof(Stream)), + Expression.Return(returnTarget, Expression.Call(MethodStreamToBytes, Expression.Convert(valueExp, typeof(Stream)))), + callToBytesExp + ) ) ) ); @@ -2304,35 +2379,125 @@ Expression LocalFuncGetExpression(bool ignoreArray = false) switch (type.FullName) { case "System.Guid": - tryparseExp = Expression.Block( - new[] { tryparseVarExp = Expression.Variable(typeof(Guid)) }, - new Expression[] { + return Expression.Block( + new[] { tryparseVarExp = Expression.Variable(typeof(Guid)) }, + Expression.IfThenElse( + Expression.TypeEqual(valueExp, type), + Expression.Return(returnTarget, valueExp), Expression.IfThenElse( - Expression.IsTrue(Expression.Call(MethodGuidTryParse, Expression.Convert(valueExp, typeof(string)), tryparseVarExp)), + Expression.AndAlso(Expression.TypeEqual(valueExp, typeof(string)), Expression.Call(MethodGuidTryParse, Expression.Convert(valueExp, typeof(string)), tryparseVarExp)), Expression.Return(returnTarget, Expression.Convert(tryparseVarExp, typeof(object))), - Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + Expression.IfThenElse( + Expression.TypeEqual(valueExp, typeof(byte[])), + Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodBytesToGuid, Expression.Convert(valueExp, typeof(byte[]))), typeof(object))), + Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + ) ) - } - ); - break; + ) + ); case "System.Numerics.BigInteger": return Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodBigIntegerParse, Expression.Call(MethodToString, valueExp)), typeof(object))); + + case "System.TimeOnly": + return Expression.IfThenElse( + Expression.TypeEqual(valueExp, type), + Expression.Return(returnTarget, valueExp), + Expression.IfThenElse( + Expression.TypeIs(valueExp, typeof(TimeSpan)), + Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodTimeOnlyFromTimeSpan, Expression.Convert(valueExp, typeof(TimeSpan))), typeof(object))), + Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodTimeOnlyParse, Expression.Convert(valueExp, typeof(string))), typeof(object))) + ) + ); case "System.TimeSpan": - ParameterExpression tryparseVarTsExp, valueStrExp; + var tryparseVarDblExp = Expression.Variable(typeof(double)); + var timeSpanExp = Expression.IfThenElse( + Expression.AndAlso( + Expression.OrElse(Expression.OrElse(Expression.OrElse(Expression.OrElse(Expression.OrElse(Expression.OrElse(Expression.OrElse(Expression.OrElse( + Expression.TypeEqual(valueExp, typeof(decimal)), Expression.TypeEqual(valueExp, typeof(int))), + Expression.TypeEqual(valueExp, typeof(long))), Expression.TypeEqual(valueExp, typeof(short))), + Expression.TypeEqual(valueExp, typeof(uint))), Expression.TypeEqual(valueExp, typeof(ulong))), Expression.TypeEqual(valueExp, typeof(ushort))), + Expression.TypeEqual(valueExp, typeof(double))), Expression.TypeEqual(valueExp, typeof(float))), + Expression.Call(MethodDoubleTryParse, Expression.Call(MethodToString, valueExp), Expression.Constant(NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarDblExp)), + Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodTimeSpanFromSeconds, tryparseVarDblExp), typeof(object))), + Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + ); + if (TypeTimeOnly != null) timeSpanExp = Expression.IfThenElse( + Expression.TypeIs(valueExp, TypeTimeOnly), + Expression.Return(returnTarget, Expression.Convert(Expression.Call(Expression.Convert(valueExp, TypeTimeOnly), MethodTimeOnlyToTimeSpan), typeof(object))), + timeSpanExp + ); return Expression.Block( - new[] { tryparseVarExp = Expression.Variable(typeof(double)), tryparseVarTsExp = Expression.Variable(typeof(TimeSpan)), valueStrExp = Expression.Variable(typeof(string)) }, - new Expression[] { - Expression.Assign(valueStrExp, Expression.Call(MethodToString, valueExp)), + new[] { tryparseVarExp = Expression.Variable(typeof(TimeSpan)), tryparseVarDblExp }, + Expression.IfThenElse( + Expression.TypeEqual(valueExp, type), + Expression.Return(returnTarget, valueExp), Expression.IfThenElse( - Expression.IsTrue(Expression.Call(MethodDoubleTryParse, valueStrExp, Expression.Constant(System.Globalization.NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarExp)), - Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodTimeSpanFromSeconds, tryparseVarExp), typeof(object))), - Expression.IfThenElse( - Expression.IsTrue(Expression.Call(MethodTimeSpanTryParse, valueStrExp, tryparseVarTsExp)), - Expression.Return(returnTarget, Expression.Convert(tryparseVarTsExp, typeof(object))), - Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) - ) + Expression.AndAlso(Expression.TypeEqual(valueExp, typeof(string)), Expression.Call(MethodTimeSpanTryParse, Expression.Convert(valueExp, typeof(string)), tryparseVarExp)), + Expression.Return(returnTarget, Expression.Convert(tryparseVarExp, typeof(object))), + timeSpanExp ) - } - ); + ) + ); + + case "System.DateOnly": + return Expression.IfThenElse( + Expression.TypeEqual(valueExp, type), + Expression.Return(returnTarget, valueExp), + Expression.IfThenElse( + Expression.TypeIs(valueExp, typeof(DateTime)), + Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodDateOnlyFromDateTime, Expression.Convert(valueExp, typeof(DateTime))), typeof(object))), + Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodDateOnlyParse, Expression.Convert(valueExp, typeof(string))), typeof(object))) + ) + ); + case "System.DateTime": + if (TypeHandlers.ContainsKey(type)) + { + foreach (var switchFunc in GetDataReaderValueBlockExpressionSwitchTypeFullName) + { + var switchFuncRet = switchFunc(returnTarget, valueExp, type); + if (switchFuncRet != null) return switchFuncRet; + } + } + Expression dateTimeExp = Expression.IfThenElse( + Expression.TypeIs(valueExp, typeof(DateTimeOffset)), + Expression.Return(returnTarget, Expression.Convert(Expression.MakeMemberAccess(Expression.Convert(valueExp, typeof(DateTimeOffset)), PropertyDateTimeOffsetDateTime), typeof(object))), + Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + ); + if (TypeDateOnly != null) dateTimeExp = Expression.IfThenElse( + Expression.TypeIs(valueExp, TypeDateOnly), + Expression.Return(returnTarget, Expression.Convert(Expression.Call(Expression.Convert(valueExp, TypeDateOnly), MethodDateOnlyToDateTime, Expression.Constant(TypeTimeOnly.CreateInstanceGetDefaultValue(), TypeTimeOnly)), typeof(object))), + dateTimeExp + ); + return Expression.Block( + new[] { tryparseVarExp = Expression.Variable(typeof(DateTime)) }, + Expression.IfThenElse( + Expression.TypeEqual(valueExp, type), + Expression.Return(returnTarget, valueExp), + Expression.IfThenElse( + Expression.AndAlso(Expression.TypeEqual(valueExp, typeof(string)), Expression.Call(MethodDateTimeTryParse, Expression.Convert(valueExp, typeof(string)), tryparseVarExp)), + Expression.Return(returnTarget, Expression.Convert(tryparseVarExp, typeof(object))), + dateTimeExp + ) + ) + ); + case "System.DateTimeOffset": + Expression dateTimeOffsetExp = Expression.IfThenElse( + Expression.TypeIs(valueExp, typeof(DateTime)), + Expression.Return(returnTarget, Expression.Convert( + Expression.New(CtorDateTimeOffsetArgsTicks, Expression.MakeMemberAccess(Expression.Convert(valueExp, typeof(DateTime)), PropertyDateTimeTicks), Expression.Constant(TimeSpan.Zero)), typeof(object))), + Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + ); + return Expression.Block( + new[] { tryparseVarExp = Expression.Variable(typeof(DateTimeOffset)) }, + Expression.IfThenElse( + Expression.TypeEqual(valueExp, type), + Expression.Return(returnTarget, valueExp), + Expression.IfThenElse( + Expression.AndAlso(Expression.TypeEqual(valueExp, typeof(string)), Expression.Call(MethodDateTimeOffsetTryParse, Expression.Convert(valueExp, typeof(string)), tryparseVarExp)), + Expression.Return(returnTarget, Expression.Convert(tryparseVarExp, typeof(object))), + dateTimeOffsetExp + ) + ) + ); case "System.Char": return Expression.IfThenElse( Expression.TypeEqual(valueExp, type), @@ -2475,38 +2640,6 @@ Expression LocalFuncGetExpression(bool ignoreArray = false) } ); break; - case "System.DateTime": - if (TypeHandlers.ContainsKey(type)) - { - foreach (var switchFunc in GetDataReaderValueBlockExpressionSwitchTypeFullName) - { - var switchFuncRet = switchFunc(returnTarget, valueExp, type); - if (switchFuncRet != null) return switchFuncRet; - } - } - tryparseExp = Expression.Block( - new[] { tryparseVarExp = Expression.Variable(typeof(DateTime)) }, - new Expression[] { - Expression.IfThenElse( - Expression.IsTrue(Expression.Call(MethodDateTimeTryParse, Expression.Convert(valueExp, typeof(string)), tryparseVarExp)), - Expression.Return(returnTarget, Expression.Convert(tryparseVarExp, typeof(object))), - Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) - ) - } - ); - break; - case "System.DateTimeOffset": - tryparseExp = Expression.Block( - new[] { tryparseVarExp = Expression.Variable(typeof(DateTimeOffset)) }, - new Expression[] { - Expression.IfThenElse( - Expression.IsTrue(Expression.Call(MethodDateTimeOffsetTryParse, Expression.Convert(valueExp, typeof(string)), tryparseVarExp)), - Expression.Return(returnTarget, Expression.Convert(tryparseVarExp, typeof(object))), - Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) - ) - } - ); - break; case "System.Boolean": tryparseBooleanExp = Expression.Return(returnTarget, Expression.Convert( @@ -2531,30 +2664,6 @@ Expression LocalFuncGetExpression(bool ignoreArray = false) Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodStringToBitArray, Expression.Call(MethodToString, valueExp)), typeof(object))) ) ); - case "System.DateOnly": - var MethodDateOnlyFromDateTime = type.GetMethod("FromDateTime", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(DateTime) }, null); - var MethodDateOnlyParse = type.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string) }, null); - return Expression.IfThenElse( - Expression.TypeEqual(valueExp, type), - Expression.Return(returnTarget, valueExp), - Expression.IfThenElse( - Expression.TypeIs(valueExp, typeof(DateTime)), - Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodDateOnlyFromDateTime, Expression.Convert(valueExp, typeof(DateTime))), typeof(object))), - Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodDateOnlyParse, Expression.Convert(valueExp, typeof(string))), typeof(object))) - ) - ); - case "System.TimeOnly": - var MethodTimeOnlyFromTimeSpan = type.GetMethod("FromTimeSpan", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(TimeSpan) }, null); - var MethodTimeOnlyParse = type.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string) }, null); - return Expression.IfThenElse( - Expression.TypeEqual(valueExp, type), - Expression.Return(returnTarget, valueExp), - Expression.IfThenElse( - Expression.TypeIs(valueExp, typeof(TimeSpan)), - Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodTimeOnlyFromTimeSpan, Expression.Convert(valueExp, typeof(TimeSpan))), typeof(object))), - Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodTimeOnlyParse, Expression.Convert(valueExp, typeof(string))), typeof(object))) - ) - ); default: if (type.IsEnum && TypeHandlers.ContainsKey(type) == false) return Expression.IfThenElse( @@ -2608,26 +2717,13 @@ Expression LocalFuncGetExpression(bool ignoreArray = false) Expression.TypeEqual(valueExp, typeof(string)), switchExp, Expression.IfThenElse( - Expression.AndAlso(Expression.Equal(Expression.Constant(type), Expression.Constant(typeof(DateTime))), Expression.TypeEqual(valueExp, typeof(DateTimeOffset))), - Expression.Return(returnTarget, Expression.Convert(Expression.MakeMemberAccess(Expression.Convert(valueExp, typeof(DateTimeOffset)), PropertyDateTimeOffsetDateTime), typeof(object))), + Expression.TypeEqual(valueExp, typeof(byte[])), Expression.IfThenElse( - Expression.AndAlso(Expression.Equal(Expression.Constant(type), Expression.Constant(typeof(DateTimeOffset))), Expression.TypeEqual(valueExp, typeof(DateTime))), - Expression.Return(returnTarget, Expression.Convert( - Expression.New(CtorDateTimeOffsetArgsTicks, Expression.MakeMemberAccess(Expression.Convert(valueExp, typeof(DateTime)), PropertyDateTimeTicks), Expression.Constant(TimeSpan.Zero)), typeof(object))), - Expression.IfThenElse( - Expression.TypeEqual(valueExp, typeof(byte[])), - Expression.IfThenElse( - Expression.Equal(Expression.Constant(type), Expression.Constant(typeof(Guid))), - Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodBytesToGuid, Expression.Convert(valueExp, typeof(byte[]))), typeof(object))), - Expression.IfThenElse( - Expression.Equal(Expression.Constant(type), Expression.Constant(typeof(string))), - Expression.Return(returnTarget, Expression.Convert(Expression.Call(Expression.Constant(DefaultEncoding), MethodEncodingGetString, Expression.Convert(valueExp, typeof(byte[]))), typeof(object))), - defaultRetExp - ) - ), - defaultRetExp - ) - ) + Expression.Equal(Expression.Constant(type), Expression.Constant(typeof(string))), + Expression.Return(returnTarget, Expression.Convert(Expression.Call(Expression.Constant(DefaultEncoding), MethodEncodingGetString, Expression.Convert(valueExp, typeof(byte[]))), typeof(object))), + defaultRetExp + ), + defaultRetExp ) ) );