- 修复 DateOnly/TimeOnly 映射问题;#1868 #1855 #1763 #939 #991

This commit is contained in:
2881099 2024-08-21 02:55:16 +08:00
parent 486015a3c2
commit 2334fe2450
36 changed files with 584 additions and 76 deletions

View File

@ -6,6 +6,7 @@
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<NoWarn>1701;1702;CS1573;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8618;CS8619;CS8620;CS8622;CS8625;CS8629;CS8714;CS1591;CS0649;CA2200</NoWarn>
</PropertyGroup>
<!--

View File

@ -4,7 +4,7 @@
<TargetFrameworks>net8.0;net7.0;net6.0;net5.0;netstandard2.1;netcoreapp3.1;netstandard2.0;net45;net40</TargetFrameworks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>FreeSql;ncc;YeXiangQin</Authors>
<Description>FreeSql is the ORM in .NetCore, .NetFramework, And Xamarin. It supports Mysql, Postgresql, SqlServer, Oracle, Sqlite, Firebird, Clickhouse, QuestDB, Odbc, Oledb, 达梦, 人大金仓, 南大通用, 虚谷, 神舟通用, 翰高, And Access</Description>
<Description>FreeSql is the ORM in .NetCore, .NetFramework, And Xamarin. It supports Mysql, Postgresql, SqlServer, Oracle, Sqlite, Firebird, Clickhouse, DuckDB, TDengine, QuestDB, Odbc, Oledb, 达梦, 人大金仓, 南大通用, 虚谷, 神舟通用, 翰高, And Access</Description>
<PackageProjectUrl>https://github.com/2881099/FreeSql/wiki/DbContext</PackageProjectUrl>
<PackageTags>FreeSql ORM DbContext</PackageTags>
<RepositoryType>git</RepositoryType>

View File

@ -707,15 +707,6 @@
<param name="modelBuilder"></param>
<returns></returns>
</member>
<member name="M:FreeSqlDbContextExtensions.ApplyConfigurationsFromAssembly(FreeSql.ICodeFirst,System.Reflection.Assembly,System.Func{System.Type,System.Boolean})">
<summary>
根据Assembly扫描所有继承IEntityTypeConfiguration&lt;T&gt;的配置类
</summary>
<param name="codeFirst"></param>
<param name="assembly"></param>
<param name="predicate"></param>
<returns></returns>
</member>
<member name="M:FreeSqlDbContextExtensions.CreateDbContext(IFreeSql)">
<summary>
创建普通数据上下文档对象

View File

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFrameworks>net8.0;net7.0;net6.0;net5.0;netcoreapp3.1;netstandard2.1;netstandard2.0;net45;net40</TargetFrameworks>
<Authors>FreeSql;ncc;YeXiangQin</Authors>
<Description>FreeSql Implementation of General Repository, Support MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/Clickhouse/QuestDB/达梦/人大金仓/南大通用/虚谷/神舟通用/翰高/Access, and read/write separation、and split table.</Description>
<Description>FreeSql Implementation of General Repository, Support MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/Clickhouse/DuckDB/TDengine/QuestDB/达梦/人大金仓/南大通用/虚谷/神舟通用/翰高/Access, and read/write separation、and split table.</Description>
<PackageProjectUrl>https://github.com/2881099/FreeSql/wiki/Repository</PackageProjectUrl>
<PackageTags>FreeSql ORM Repository</PackageTags>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>

View File

@ -16,6 +16,68 @@ namespace FreeSql.Tests.Duckdb
{
IFreeSql fsql => g.duckdb;
[Fact]
public void DateOnlyTimeOnly()
{
var item = new test_DateOnlyTimeOnly01 { testFieldDateOnly = DateOnly.FromDateTime(DateTime.Now) };
item.Id = (int)fsql.Insert(item).ExecuteIdentity();
var newitem = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item.Id).ToOne();
var now = DateTime.Parse("2024-8-20 23:00:11");
var item2 = new test_DateOnlyTimeOnly01
{
testFieldDateTime = now,
testFieldDateTimeNullable = now.AddDays(-1),
testFieldDateOnly = DateOnly.FromDateTime(now),
testFieldDateOnlyNullable = DateOnly.FromDateTime(now.AddDays(-1)),
testFieldTimeSpan = TimeSpan.FromHours(16),
testFieldTimeSpanNullable = TimeSpan.FromSeconds(90),
testFieldTimeOnly = TimeOnly.FromTimeSpan(TimeSpan.FromHours(11)),
testFieldTimeOnlyNullable = TimeOnly.FromTimeSpan(TimeSpan.FromSeconds(90)),
};
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')");
item2.Id = (int)fsql.Insert(item2).NoneParameter().ExecuteIdentity();
var item3NP = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item2.Id).ToOne();
Assert.Equal(item3NP.testFieldDateOnly, item2.testFieldDateOnly);
Assert.Equal(item3NP.testFieldDateOnlyNullable, item2.testFieldDateOnlyNullable);
Assert.True(Math.Abs((item3NP.testFieldTimeOnly - item2.testFieldTimeOnly).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyNullable - item2.testFieldTimeOnlyNullable).Value.TotalSeconds) < 1);
item2.Id = (int)fsql.Insert(item2).ExecuteIdentity();
item3NP = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item2.Id).ToOne();
Assert.Equal(item3NP.testFieldDateOnly, item2.testFieldDateOnly);
Assert.Equal(item3NP.testFieldDateOnlyNullable, item2.testFieldDateOnlyNullable);
Assert.True(Math.Abs((item3NP.testFieldTimeOnly - item2.testFieldTimeOnly).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyNullable - item2.testFieldTimeOnlyNullable).Value.TotalSeconds) < 1);
var items = fsql.Select<test_DateOnlyTimeOnly01>().ToList();
var itemstb = fsql.Select<test_DateOnlyTimeOnly01>().ToDataTable();
}
class test_DateOnlyTimeOnly01
{
[Column(IsIdentity = true, IsPrimary = true)]
public int Id { get; set; }
public TimeSpan testFieldTimeSpan { get; set; }
public TimeOnly testFieldTimeOnly { get; set; }
[Column(ServerTime = DateTimeKind.Local)]
public DateTime testFieldDateTime { get; set; }
public DateOnly testFieldDateOnly { get; set; }
public TimeSpan? testFieldTimeSpanNullable { get; set; }
public TimeOnly? testFieldTimeOnlyNullable { get; set; }
[Column(ServerTime = DateTimeKind.Local)]
public DateTime? testFieldDateTimeNullable { get; set; }
public DateOnly? testFieldDateOnlyNullable { get; set; }
}
[Fact]
public void UInt256Crud2()
{

View File

@ -17,6 +17,69 @@ namespace FreeSql.Tests.KingbaseES
public class KingbaseESCodeFirstTest
{
[Fact]
public void DateOnlyTimeOnly()
{
var fsql = g.kingbaseES;
var item = new test_DateOnlyTimeOnly01 { testFieldDateOnly = DateOnly.FromDateTime(DateTime.Now) };
item.Id = (int)fsql.Insert(item).ExecuteIdentity();
var newitem = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item.Id).ToOne();
var now = DateTime.Parse("2024-8-20 23:00:11");
var item2 = new test_DateOnlyTimeOnly01
{
testFieldDateTime = now,
testFieldDateTimeNullable = now.AddDays(-1),
testFieldDateOnly = DateOnly.FromDateTime(now),
testFieldDateOnlyNullable = DateOnly.FromDateTime(now.AddDays(-1)),
testFieldTimeSpan = TimeSpan.FromHours(16),
testFieldTimeSpanNullable = TimeSpan.FromSeconds(90),
testFieldTimeOnly = TimeOnly.FromTimeSpan(TimeSpan.FromHours(11)),
testFieldTimeOnlyNullable = TimeOnly.FromTimeSpan(TimeSpan.FromSeconds(90)),
};
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('16:0:0', '11:0:0', current_timestamp, '2024-08-20', '0:1:30', '0:1:30', current_timestamp, '2024-08-19')");
item2.Id = (int)fsql.Insert(item2).NoneParameter().ExecuteIdentity();
var item3NP = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item2.Id).ToOne();
Assert.Equal(item3NP.testFieldDateOnly, item2.testFieldDateOnly);
Assert.Equal(item3NP.testFieldDateOnlyNullable, item2.testFieldDateOnlyNullable);
Assert.True(Math.Abs((item3NP.testFieldTimeOnly - item2.testFieldTimeOnly).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyNullable - item2.testFieldTimeOnlyNullable).Value.TotalSeconds) < 1);
item2.Id = (int)fsql.Insert(item2).ExecuteIdentity();
item3NP = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item2.Id).ToOne();
Assert.Equal(item3NP.testFieldDateOnly, item2.testFieldDateOnly);
Assert.Equal(item3NP.testFieldDateOnlyNullable, item2.testFieldDateOnlyNullable);
Assert.True(Math.Abs((item3NP.testFieldTimeOnly - item2.testFieldTimeOnly).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyNullable - item2.testFieldTimeOnlyNullable).Value.TotalSeconds) < 1);
var items = fsql.Select<test_DateOnlyTimeOnly01>().ToList();
var itemstb = fsql.Select<test_DateOnlyTimeOnly01>().ToDataTable();
}
class test_DateOnlyTimeOnly01
{
[Column(IsIdentity = true, IsPrimary = true)]
public int Id { get; set; }
public TimeSpan testFieldTimeSpan { get; set; }
public TimeOnly testFieldTimeOnly { get; set; }
[Column(ServerTime = DateTimeKind.Local)]
public DateTime testFieldDateTime { get; set; }
public DateOnly testFieldDateOnly { get; set; }
public TimeSpan? testFieldTimeSpanNullable { get; set; }
public TimeOnly? testFieldTimeOnlyNullable { get; set; }
[Column(ServerTime = DateTimeKind.Local)]
public DateTime? testFieldDateTimeNullable { get; set; }
public DateOnly? testFieldDateOnlyNullable { get; set; }
}
[Fact]
public void Test_0String()
{

View File

@ -11,6 +11,70 @@ namespace FreeSql.Tests.MySql
{
public class MySqlCodeFirstTest
{
[Fact]
public void DateOnlyTimeOnly()
{
var fsql = g.mysql;
var item = new test_DateOnlyTimeOnly01 { testFieldDateOnly = DateOnly.FromDateTime(DateTime.Now) };
item.Id = (int)fsql.Insert(item).ExecuteIdentity();
var newitem = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item.Id).ToOne();
var now = DateTime.Parse("2024-8-20 23:00:11");
var item2 = new test_DateOnlyTimeOnly01
{
testFieldDateTime = now,
testFieldDateTimeNullable = now.AddDays(-1),
testFieldDateOnly = DateOnly.FromDateTime(now),
testFieldDateOnlyNullable = DateOnly.FromDateTime(now.AddDays(-1)),
testFieldTimeSpan = TimeSpan.FromHours(16),
testFieldTimeSpanNullable = TimeSpan.FromSeconds(90),
testFieldTimeOnly = TimeOnly.FromTimeSpan(TimeSpan.FromHours(11)),
testFieldTimeOnlyNullable = TimeOnly.FromTimeSpan(TimeSpan.FromSeconds(90)),
};
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('16:0:0', '11:0:0', now(3), '2024-08-20', '0:1:30', '0:1:30', now(3), '2024-08-19')");
item2.Id = (int)fsql.Insert(item2).NoneParameter().ExecuteIdentity();
var item3NP = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item2.Id).ToOne();
Assert.Equal(item3NP.testFieldDateOnly, item2.testFieldDateOnly);
Assert.Equal(item3NP.testFieldDateOnlyNullable, item2.testFieldDateOnlyNullable);
Assert.True(Math.Abs((item3NP.testFieldTimeOnly - item2.testFieldTimeOnly).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyNullable - item2.testFieldTimeOnlyNullable).Value.TotalSeconds) < 1);
item2.Id = (int)fsql.Insert(item2).ExecuteIdentity();
item3NP = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item2.Id).ToOne();
Assert.Equal(item3NP.testFieldDateOnly, item2.testFieldDateOnly);
Assert.Equal(item3NP.testFieldDateOnlyNullable, item2.testFieldDateOnlyNullable);
Assert.True(Math.Abs((item3NP.testFieldTimeOnly - item2.testFieldTimeOnly).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyNullable - item2.testFieldTimeOnlyNullable).Value.TotalSeconds) < 1);
var items = fsql.Select<test_DateOnlyTimeOnly01>().ToList();
var itemstb = fsql.Select<test_DateOnlyTimeOnly01>().ToDataTable();
}
class test_DateOnlyTimeOnly01
{
[Column(IsIdentity = true, IsPrimary = true)]
public int Id { get; set; }
public TimeSpan testFieldTimeSpan { get; set; }
public TimeOnly testFieldTimeOnly { get; set; }
[Column(ServerTime = DateTimeKind.Local)]
public DateTime testFieldDateTime { get; set; }
public DateOnly testFieldDateOnly { get; set; }
public TimeSpan? testFieldTimeSpanNullable { get; set; }
public TimeOnly? testFieldTimeOnlyNullable { get; set; }
[Column(ServerTime = DateTimeKind.Local)]
public DateTime? testFieldDateTimeNullable { get; set; }
public DateOnly? testFieldDateOnlyNullable { get; set; }
}
[Fact]
public void Test_Bool01()
{

View File

@ -28,20 +28,21 @@ namespace FreeSql.Tests.PostgreSQL
var newitem = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item.Id).ToOne();
var now = DateTime.Parse("2024-8-20 23:00:11");
var item2 = new test_DateOnlyTimeOnly01
{
testFieldDateTime = DateTime.Now,
testFieldDateTimeArray = new[] { DateTime.Now, DateTime.Now.AddHours(2) },
testFieldDateTimeArrayNullable = new DateTime?[] { DateTime.Now, null, DateTime.Now.AddHours(2) },
testFieldDateTimeNullable = DateTime.Now.AddDays(-1),
testFieldDateOnly = DateOnly.FromDateTime(DateTime.Now),
testFieldDateOnlyArray = new[] { DateOnly.FromDateTime(DateTime.Now), DateOnly.FromDateTime(DateTime.Now.AddHours(2)) },
testFieldDateOnlyArrayNullable = new DateOnly?[] { DateOnly.FromDateTime(DateTime.Now), null, DateOnly.FromDateTime(DateTime.Now.AddHours(2)) },
testFieldDateOnlyNullable = DateOnly.FromDateTime(DateTime.Now.AddDays(-1)),
testFieldDateTime = now,
testFieldDateTimeArray = new[] { now, now.AddHours(2) },
testFieldDateTimeArrayNullable = new DateTime?[] { now, null, now.AddHours(2) },
testFieldDateTimeNullable = now.AddDays(-1),
testFieldDateOnly = DateOnly.FromDateTime(now),
testFieldDateOnlyArray = new[] { DateOnly.FromDateTime(now), DateOnly.FromDateTime(now.AddHours(2)) },
testFieldDateOnlyArrayNullable = new DateOnly?[] { DateOnly.FromDateTime(now), null, DateOnly.FromDateTime(now.AddHours(2)) },
testFieldDateOnlyNullable = DateOnly.FromDateTime(now.AddDays(-1)),
testFieldTimeSpan = TimeSpan.FromDays(1),
testFieldTimeSpanArray = new[] { TimeSpan.FromDays(1), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(60) },
testFieldTimeSpanArrayNullable = new TimeSpan?[] { TimeSpan.FromDays(1), TimeSpan.FromSeconds(10), null, TimeSpan.FromSeconds(60) },
testFieldTimeSpan = TimeSpan.FromHours(16),
testFieldTimeSpanArray = new[] { TimeSpan.FromHours(16), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(60) },
testFieldTimeSpanArrayNullable = new TimeSpan?[] { TimeSpan.FromHours(16), TimeSpan.FromSeconds(10), null, TimeSpan.FromSeconds(60) },
testFieldTimeSpanNullable = TimeSpan.FromSeconds(90),
testFieldTimeOnly = TimeOnly.FromTimeSpan(TimeSpan.FromHours(11)),
testFieldTimeOnlyArray = new[] { TimeOnly.FromTimeSpan(TimeSpan.FromHours(11)), TimeOnly.FromTimeSpan(TimeSpan.FromSeconds(10)), TimeOnly.FromTimeSpan(TimeSpan.FromSeconds(60)) },
@ -51,15 +52,37 @@ namespace FreeSql.Tests.PostgreSQL
var sqlPar = fsql.Insert(item2).ToSql();
var sqlText = fsql.Insert(item2).NoneParameter().ToSql();
var item3NP = fsql.Insert(item2).NoneParameter().ExecuteInserted();
var item3NP = fsql.Insert(item2).NoneParameter().ExecuteInserted()[0];
Assert.Equal(item3NP.testFieldDateOnly, item2.testFieldDateOnly);
Assert.Equal(item3NP.testFieldDateOnlyArray[0], item2.testFieldDateOnlyArray[0]);
Assert.Equal(item3NP.testFieldDateOnlyArray[1], item2.testFieldDateOnlyArray[1]);
Assert.Equal(item3NP.testFieldDateOnlyNullable, item2.testFieldDateOnlyNullable);
Assert.True(Math.Abs((item3NP.testFieldTimeOnly - item2.testFieldTimeOnly).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyArray[0] - item2.testFieldTimeOnlyArray[0]).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyArray[1] - item2.testFieldTimeOnlyArray[1]).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyNullable - item2.testFieldTimeOnlyNullable).Value.TotalSeconds) < 1);
var item3 = fsql.Insert(item2).ExecuteInserted().First();
var newitem2 = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item3.Id).ToOne();
Assert.True(item2.testFieldDateTime.Subtract( newitem2.testFieldDateTime).TotalSeconds <= 0);
item3NP = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item3.Id).ToOne();
Assert.Equal(item3NP.testFieldDateOnly, item2.testFieldDateOnly);
Assert.Equal(item3NP.testFieldDateOnlyArray[0], item2.testFieldDateOnlyArray[0]);
Assert.Equal(item3NP.testFieldDateOnlyArray[1], item2.testFieldDateOnlyArray[1]);
Assert.Equal(item3NP.testFieldDateOnlyNullable, item2.testFieldDateOnlyNullable);
Assert.True(Math.Abs((item3NP.testFieldTimeOnly - item2.testFieldTimeOnly).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyArray[0] - item2.testFieldTimeOnlyArray[0]).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyArray[1] - item2.testFieldTimeOnlyArray[1]).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyNullable - item2.testFieldTimeOnlyNullable).Value.TotalSeconds) < 1);
item3 = fsql.Insert(item2).NoneParameter().ExecuteInserted().First();
newitem2 = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item3.Id).ToOne();
Assert.True(item3.testFieldDateTime.Subtract(newitem2.testFieldDateTime).TotalSeconds <= 0);
item3NP = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item3.Id).ToOne();
Assert.Equal(item3NP.testFieldDateOnly, item2.testFieldDateOnly);
Assert.Equal(item3NP.testFieldDateOnlyArray[0], item2.testFieldDateOnlyArray[0]);
Assert.Equal(item3NP.testFieldDateOnlyArray[1], item2.testFieldDateOnlyArray[1]);
Assert.Equal(item3NP.testFieldDateOnlyNullable, item2.testFieldDateOnlyNullable);
Assert.True(Math.Abs((item3NP.testFieldTimeOnly - item2.testFieldTimeOnly).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyArray[0] - item2.testFieldTimeOnlyArray[0]).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyArray[1] - item2.testFieldTimeOnlyArray[1]).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP.testFieldTimeOnlyNullable - item2.testFieldTimeOnlyNullable).Value.TotalSeconds) < 1);
var items = fsql.Select<test_DateOnlyTimeOnly01>().ToList();
var itemstb = fsql.Select<test_DateOnlyTimeOnly01>().ToDataTable();

View File

@ -12,6 +12,81 @@ namespace FreeSql.Tests.SqlServer
{
public class SqlServerCodeFirstTest
{
[Fact]
public void DateOnlyTimeOnly()
{
var fsql = g.sqlserver;
var item = new test_DateOnlyTimeOnly01 { testFieldDateOnly = DateOnly.FromDateTime(DateTime.Now) };
item.Id = (int)fsql.Insert(item).ExecuteIdentity();
fsql.Aop.AuditDataReader += (s, e) =>
{
;
};
var newitem = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item.Id).ToOne();
var now = DateTime.Parse("2024-8-20 23:00:11");
var item2 = new test_DateOnlyTimeOnly01
{
testFieldDateTime = now,
testFieldDateTimeNullable = now.AddDays(-1),
testFieldDateOnly = DateOnly.FromDateTime(now),
testFieldDateOnlyNullable = DateOnly.FromDateTime(now.AddDays(-1)),
testFieldTimeSpan = TimeSpan.FromHours(16),
testFieldTimeSpanNullable = TimeSpan.FromSeconds(90),
testFieldTimeOnly = TimeOnly.FromTimeSpan(TimeSpan.FromHours(11)),
testFieldTimeOnlyNullable = TimeOnly.FromTimeSpan(TimeSpan.FromSeconds(90)),
};
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('16:0:0.0', '11:0:0', getdate(), '2024-08-20', '0:1:30.0', '0:1:30', getdate(), '2024-08-19')");
var item3NP = fsql.Insert(item2).NoneParameter().ExecuteInserted();
Assert.Equal(item3NP[0].testFieldDateOnly, item2.testFieldDateOnly);
Assert.Equal(item3NP[0].testFieldDateOnlyNullable, item2.testFieldDateOnlyNullable);
Assert.True(Math.Abs((item3NP[0].testFieldTimeOnly - item2.testFieldTimeOnly).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP[0].testFieldTimeOnlyNullable - item2.testFieldTimeOnlyNullable).Value.TotalSeconds) < 1);
var item3 = fsql.Insert(item2).ExecuteInserted().First();
var newitem2 = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item3.Id).ToOne();
Assert.Equal(item3NP[0].testFieldDateOnly, item2.testFieldDateOnly);
Assert.Equal(item3NP[0].testFieldDateOnlyNullable, item2.testFieldDateOnlyNullable);
Assert.True(Math.Abs((item3NP[0].testFieldTimeOnly - item2.testFieldTimeOnly).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP[0].testFieldTimeOnlyNullable - item2.testFieldTimeOnlyNullable).Value.TotalSeconds) < 1);
item3 = fsql.Insert(item2).NoneParameter().ExecuteInserted().First();
newitem2 = fsql.Select<test_DateOnlyTimeOnly01>().Where(a => a.Id == item3.Id).ToOne();
Assert.Equal(item3NP[0].testFieldDateOnly, item2.testFieldDateOnly);
Assert.Equal(item3NP[0].testFieldDateOnlyNullable, item2.testFieldDateOnlyNullable);
Assert.True(Math.Abs((item3NP[0].testFieldTimeOnly - item2.testFieldTimeOnly).TotalSeconds) < 1);
Assert.True(Math.Abs((item3NP[0].testFieldTimeOnlyNullable - item2.testFieldTimeOnlyNullable).Value.TotalSeconds) < 1);
var items = fsql.Select<test_DateOnlyTimeOnly01>().ToList();
var itemstb = fsql.Select<test_DateOnlyTimeOnly01>().ToDataTable();
}
class test_DateOnlyTimeOnly01
{
[Column(IsIdentity = true, IsPrimary = true)]
public int Id { get; set; }
public TimeSpan testFieldTimeSpan { get; set; }
public TimeOnly testFieldTimeOnly { get; set; }
[Column(ServerTime = DateTimeKind.Local)]
public DateTime testFieldDateTime { get; set; }
public DateOnly testFieldDateOnly { get; set; }
public TimeSpan? testFieldTimeSpanNullable { get; set; }
public TimeOnly? testFieldTimeOnlyNullable { get; set; }
[Column(ServerTime = DateTimeKind.Local)]
public DateTime? testFieldDateTimeNullable { get; set; }
public DateOnly? testFieldDateOnlyNullable { get; set; }
}
[Fact]
public void VersionInt()
{

View File

@ -4,7 +4,7 @@
<TargetFrameworks>netstandard2.1;netstandard2.0;net451;net45;net40</TargetFrameworks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>FreeSql;ncc;YeXiangQin</Authors>
<Description>FreeSql is the ORM in .NetCore, .NetFramework, And Xamarin. It supports Mysql, Postgresql, SqlServer, Oracle, Sqlite, Firebird, Clickhouse, QuestDB, Odbc, Oledb, 达梦, 人大金仓, 南大通用, 虚谷, 神舟通用, 翰高, And Access</Description>
<Description>FreeSql is the ORM in .NetCore, .NetFramework, And Xamarin. It supports Mysql, Postgresql, SqlServer, Oracle, Sqlite, Firebird, Clickhouse, DuckDB, TDengine, QuestDB, Odbc, Oledb, 达梦, 人大金仓, 南大通用, 虚谷, 神舟通用, 翰高, And Access</Description>
<PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl>
<RepositoryUrl>https://github.com/2881099/FreeSql</RepositoryUrl>
<RepositoryType>git</RepositoryType>

View File

@ -6345,3 +6345,126 @@
</member>
</members>
</doc>
<returns></returns>
</member>
<member name="M:IFreeSql.Insert``1(System.Collections.Generic.List{``0})">
<summary>
插入数据,传入实体集合
</summary>
<typeparam name="T1"></typeparam>
<param name="source"></param>
<returns></returns>
</member>
<member name="M:IFreeSql.Insert``1(System.Collections.Generic.IEnumerable{``0})">
<summary>
插入数据,传入实体集合
</summary>
<typeparam name="T1"></typeparam>
<param name="source"></param>
<returns></returns>
</member>
<member name="M:IFreeSql.InsertOrUpdate``1">
<summary>
插入或更新数据,此功能依赖数据库特性(低版本可能不支持),参考如下:<para></para>
MySql 5.6+: on duplicate key update<para></para>
PostgreSQL 9.4+: on conflict do update<para></para>
SqlServer 2008+: merge into<para></para>
Oracle 11+: merge into<para></para>
Sqlite: replace into<para></para>
DuckDB: on conflict do update<para></para>
达梦: merge into<para></para>
人大金仓on conflict do update<para></para>
神通merge into<para></para>
MsAccess不支持<para></para>
注意区别FreeSql.Repository 仓储也有 InsertOrUpdate 方法(不依赖数据库特性)
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Update``1">
<summary>
修改数据
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Update``1(System.Object)">
<summary>
修改数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
</summary>
<typeparam name="T1"></typeparam>
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
<returns></returns>
</member>
<member name="M:IFreeSql.Select``1">
<summary>
查询数据
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Select``1(System.Object)">
<summary>
查询数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
</summary>
<typeparam name="T1"></typeparam>
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
<returns></returns>
</member>
<member name="M:IFreeSql.Delete``1">
<summary>
删除数据
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Delete``1(System.Object)">
<summary>
删除数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}
</summary>
<typeparam name="T1"></typeparam>
<param name="dywhere">主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合</param>
<returns></returns>
</member>
<member name="M:IFreeSql.Transaction(System.Action)">
<summary>
开启事务(不支持异步)<para></para>
v1.5.0 关闭了线程事务超时自动提交的机制
</summary>
<param name="handler">事务体 () => {}</param>
</member>
<member name="M:IFreeSql.Transaction(System.Data.IsolationLevel,System.Action)">
<summary>
开启事务(不支持异步)<para></para>
v1.5.0 关闭了线程事务超时自动提交的机制
</summary>
<param name="isolationLevel"></param>
<param name="handler">事务体 () => {}</param>
</member>
<member name="P:IFreeSql.Ado">
<summary>
数据库访问对象
</summary>
</member>
<member name="P:IFreeSql.Aop">
<summary>
所有拦截方法都在这里
</summary>
</member>
<member name="P:IFreeSql.CodeFirst">
<summary>
CodeFirst 模式开发相关方法
</summary>
</member>
<member name="P:IFreeSql.DbFirst">
<summary>
DbFirst 模式开发相关方法
</summary>
</member>
<member name="P:IFreeSql.GlobalFilter">
<summary>
全局过滤设置,可默认附加为 Select/Update/Delete 条件
</summary>
</member>
</members>
</doc>

View File

@ -2531,14 +2531,36 @@ namespace FreeSql.Internal
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.Block(
Expression.IfThenElse(
return Expression.IfThenElse(
Expression.Equal(Expression.TypeAs(valueExp, typeof(string)), Expression.Constant(string.Empty)),
Expression.Return(returnTarget, Expression.Convert(Expression.Default(type), typeof(object))),
Expression.Return(returnTarget, Expression.Call(MethodEnumParse, Expression.Constant(type, typeof(Type)), Expression.Call(MethodToString, valueExp), Expression.Constant(true, typeof(bool))))
)
);
foreach (var switchFunc in GetDataReaderValueBlockExpressionSwitchTypeFullName)
{

View File

@ -27,6 +27,7 @@ namespace FreeSql.Custom.SqlServer
{
if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}";
if (value?.Equals(DateTime.MinValue) == true) value = new DateTime(1970, 1, 1);
else if (value?.Equals(DateTimeOffset.MinValue) == true) value = new DateTime(1970, 1, 1);
var ret = Factory.CreateParameter();
ret.ParameterName = QuoteParamterName(parameterName);
ret.Value = value;
@ -40,6 +41,7 @@ namespace FreeSql.Custom.SqlServer
Utils.GetDbParamtersByObject<DbParameter>(sql, obj, null, (name, type, value) =>
{
if (value?.Equals(DateTime.MinValue) == true) value = new DateTime(1970, 1, 1);
else if (value?.Equals(DateTimeOffset.MinValue) == true) value = new DateTime(1970, 1, 1);
var ret = Factory.CreateParameter();
ret.ParameterName = $"@{name}";
ret.Value = value;

View File

@ -71,7 +71,7 @@ namespace FreeSql.Duckdb
else if (param is TimeOnly || param is TimeOnly?)
{
var ts = (TimeOnly)param;
return $"'{ts.Hour}:{ts.Minute}:{ts.Second}.{ts.Millisecond}'";
return $"time '{ts.Hour}:{ts.Minute}:{ts.Second}'";
}
#endif

View File

@ -41,7 +41,7 @@ namespace FreeSql.Duckdb
{ typeof(DateTime).FullName, CsToDb.New(DuckDBType.Timestamp, "timestamp", "timestamp NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, CsToDb.New(DuckDBType.Timestamp, "timestamp", "timestamp", false, true, null) },
#if net60
{ typeof(TimeOnly).FullName, CsToDb.New(DuckDBType.Time, "time", "time NOT NULL", false, false, 0) },{ typeof(TimeOnly?).FullName, CsToDb.New(DuckDBType.Time, "time", "time", false, true, null) },
{ typeof(TimeOnly).FullName, CsToDb.New(DuckDBType.Time, "time", "time NOT NULL", false, false, TimeOnly.MinValue) },{ typeof(TimeOnly?).FullName, CsToDb.New(DuckDBType.Time, "time", "time", false, true, null) },
{ typeof(DateOnly).FullName, CsToDb.New(DuckDBType.Date, "date", "date NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateOnly?).FullName, CsToDb.New(DuckDBType.Date, "date", "date", false, true, null) },
#endif
@ -53,18 +53,48 @@ namespace FreeSql.Duckdb
{ typeof(BitArray).FullName, CsToDb.New(DuckDBType.Bit, "bit", "bit", false, null, new BitArray(new byte[64])) },
{ typeof(BigInteger).FullName, CsToDb.New(DuckDBType.HugeInt, "hugeint","hugeint NOT NULL", false, false, 0) },{ typeof(BigInteger?).FullName, CsToDb.New(DuckDBType.HugeInt, "hugeint","hugeint", false, true, null) },
{ typeof(Dictionary<string, object>).FullName, CsToDb.New(DuckDBType.Struct, "struct", "struct", false, null, new Dictionary<string, object>()) },
};
public override DbInfoResult GetDbInfo(Type type)
{
//int[]..List<int>
var isarray = type.FullName != "System.Byte[]" && type.IsArray;
var elementType = isarray ? type.GetElementType() : type;
Type elementType = isarray ? type.GetElementType().NullableTypeOrThis() : type;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
{
isarray = true;
elementType = type.GenericTypeArguments[0].NullableTypeOrThis();
}
var info = GetDbInfoNoneArray(elementType);
if (info == null) return null;
if (isarray == false) return new DbInfoResult((int)info.type, info.dbtype, info.dbtypeFull, info.isnullable, info.defaultValue);
if (isarray)
{
var dbtypefull = Regex.Replace(info.dbtypeFull, $@"{info.dbtype}(\s*\([^\)]+\))?", "$0[]").Replace(" NOT NULL", "");
return new DbInfoResult((int)(info.type | DuckDBType.Array), $"{info.dbtype}[]", dbtypefull, null, Array.CreateInstance(elementType, 0));
}
if (type.IsGenericType)
{
var typeDefinition = type.GetGenericTypeDefinition();
//struct
if (typeDefinition == typeof(Dictionary<string, object>))
{
}
//map
if (typeDefinition == typeof(Dictionary<,>))
{
var tkeyInfo = GetDbInfoNoneArray(type.GenericTypeArguments[0].NullableTypeOrThis());
if (tkeyInfo == null) return null;
var tvalInfo = GetDbInfoNoneArray(type.GenericTypeArguments[1].NullableTypeOrThis());
if (tvalInfo == null) return null;
var dbtype = $"map({tkeyInfo.dbtype},{tvalInfo.dbtype})";
return new DbInfoResult((int)(info.type | DuckDBType.Array), dbtype, dbtype, null, Array.CreateInstance(elementType, 0));
}
}
return new DbInfoResult((int)info.type, info.dbtype, info.dbtypeFull, info.isnullable, info.defaultValue);
}
CsToDb<DuckDBType> GetDbInfoNoneArray(Type type)
{
if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return trydc;

View File

@ -17,6 +17,10 @@ namespace FreeSql.Duckdb
{
if (Interlocked.Exchange(ref _firstInit, 0) == 1) //不能放在 static ctor .NetFramework 可能报初始化类型错误
{
#if net60
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(DateOnly)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(TimeOnly)] = true;
#endif
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(BigInteger)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(BitArray)] = true;
Select0Provider._dicMethodDataReaderGetValue[typeof(Guid)] = typeof(DbDataReader).GetMethod("GetGuid", new Type[] { typeof(int) });

View File

@ -18,7 +18,7 @@
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
<Version>3.5.100-preview20240725</Version>
<Version>3.5.100-preview20240819</Version>
<PackageReadmeFile>readme.md</PackageReadmeFile>
</PropertyGroup>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>net8.0;net7.0;net6.0;netstandard2.0;net461</TargetFrameworks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>FreeSql;ncc;YeXiangQin</Authors>
<Description>FreeSql 数据库实现,基于 人大金仓数据库 V008R003/V008R006 Ado.Net (Kdbndp)</Description>
@ -50,5 +50,8 @@
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<DefineConstants>ns20;netstandard20</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net8.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net6.0'">
<DefineConstants>net60</DefineConstants>
</PropertyGroup>
</Project>

View File

@ -72,7 +72,7 @@ namespace FreeSql.KingbaseES
else if (param is TimeOnly || param is TimeOnly?)
{
var ts = (TimeOnly)param;
return $"'{ts.Hour}:{ts.Minute}:{ts.Second}.{ts.Millisecond}'";
return $"'{ts.Hour}:{ts.Minute}:{ts.Second}'";
}
#endif

View File

@ -43,7 +43,7 @@ namespace FreeSql.KingbaseES
{ typeof(DateTime).FullName, CsToDb.New(KdbndpDbType.Timestamp, "timestamp", "timestamp NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, CsToDb.New(KdbndpDbType.Timestamp, "timestamp", "timestamp", false, true, null) },
#if net60
{ typeof(TimeOnly).FullName, CsToDb.New(KdbndpDbType.Time, "time", "time NOT NULL", false, false, 0) },{ typeof(TimeOnly?).FullName, CsToDb.New(KdbndpDbType.Time, "time", "time", false, true, null) },
{ typeof(TimeOnly).FullName, CsToDb.New(KdbndpDbType.Time, "time", "time NOT NULL", false, false, TimeOnly.MinValue) },{ typeof(TimeOnly?).FullName, CsToDb.New(KdbndpDbType.Time, "time", "time", false, true, null) },
{ typeof(DateOnly).FullName, CsToDb.New(KdbndpDbType.Date, "date", "date NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateOnly?).FullName, CsToDb.New(KdbndpDbType.Date, "date", "date", false, true, null) },
#endif

View File

@ -24,6 +24,10 @@ namespace FreeSql.KingbaseES
{
if (Interlocked.Exchange(ref _firstInit, 0) == 1) //不能放在 static ctor .NetFramework 可能报初始化类型错误
{
#if net60
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(DateOnly)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(TimeOnly)] = true;
#endif
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(BigInteger)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(BitArray)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(KdbndpPoint)] = true;

View File

@ -67,6 +67,12 @@ namespace FreeSql.KingbaseES
} },
{ typeof((IPAddress Address, int Subnet)[]).FullName, a => getParamterArrayValue(typeof((IPAddress Address, int Subnet)), a, (IPAddress.Any, 0)) },
{ typeof((IPAddress Address, int Subnet)?[]).FullName, a => getParamterArrayValue(typeof((IPAddress Address, int Subnet)?), a, null) },
#if net60
{ typeof(DateOnly[]).FullName, a => getParamterArrayValue(typeof(DateTime), a, null) },
{ typeof(DateOnly?[]).FullName, a => getParamterArrayValue(typeof(DateTime?), a, null) },
{ typeof(TimeOnly[]).FullName, a => getParamterArrayValue(typeof(TimeSpan), a, null) },
{ typeof(TimeOnly?[]).FullName, a => getParamterArrayValue(typeof(TimeSpan?), a, null) },
#endif
};
static object getParamterValue(Type type, object value, int level = 0)
{
@ -85,6 +91,10 @@ namespace FreeSql.KingbaseES
}
if (type.IsNullableType()) type = type.GenericTypeArguments.First();
if (type.IsEnum) return (int)value;
#if net60
if (type == typeof(DateOnly)) return ((DateOnly)value).ToDateTime(TimeOnly.MinValue);
if (type == typeof(TimeOnly)) return ((TimeOnly)value).ToTimeSpan();
#endif
if (dicGetParamterValue.TryGetValue(type.FullName, out var trydic)) return trydic(value);
return value;
}

View File

@ -73,7 +73,7 @@ namespace FreeSql.MySql
else if (param is TimeOnly || param is TimeOnly?)
{
var ts = (TimeOnly)param;
return $"'{ts.Hour}:{ts.Minute}:{ts.Second}.{ts.Millisecond}'";
return $"'{ts.Hour}:{ts.Minute}:{ts.Second}'";
}
#endif

View File

@ -44,7 +44,7 @@ namespace FreeSql.MySql
{ typeof(DateTime).FullName, CsToDb.New(MySqlDbType.DateTime, "datetime(3)", "datetime(3) NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, CsToDb.New(MySqlDbType.DateTime, "datetime(3)", "datetime(3)", false, true, null) },
#if net60
{ typeof(TimeOnly).FullName, CsToDb.New(MySqlDbType.Time, "time", "time NOT NULL", false, false, 0) },{ typeof(TimeOnly?).FullName, CsToDb.New(MySqlDbType.Time, "time", "time", false, true, null) },
{ typeof(TimeOnly).FullName, CsToDb.New(MySqlDbType.Time, "time", "time NOT NULL", false, false, TimeOnly.MinValue) },{ typeof(TimeOnly?).FullName, CsToDb.New(MySqlDbType.Time, "time", "time", false, true, null) },
{ typeof(DateOnly).FullName, CsToDb.New(MySqlDbType.Date, "date", "date NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateOnly?).FullName, CsToDb.New(MySqlDbType.Date, "date", "date", false, true, null) },
#endif

View File

@ -18,6 +18,10 @@ namespace FreeSql.MySql
{
if (Interlocked.Exchange(ref _firstInit, 0) == 1) //不能放在 static ctor .NetFramework 可能报初始化类型错误
{
#if net60
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(DateOnly)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(TimeOnly)] = true;
#endif
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(MygisPoint)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(MygisLineString)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(MygisPolygon)] = true;

View File

@ -25,6 +25,7 @@ namespace FreeSql.Odbc.SqlServer
{
if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}";
if (value?.Equals(DateTime.MinValue) == true) value = new DateTime(1970, 1, 1);
else if (value?.Equals(DateTimeOffset.MinValue) == true) value = new DateTime(1970, 1, 1);
var ret = new OdbcParameter { ParameterName = QuoteParamterName(parameterName), Value = value };
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) ret.OdbcType = (OdbcType)tp.Value;
@ -36,6 +37,7 @@ namespace FreeSql.Odbc.SqlServer
Utils.GetDbParamtersByObject<OdbcParameter>(sql, obj, null, (name, type, value) =>
{
if (value?.Equals(DateTime.MinValue) == true) value = new DateTime(1970, 1, 1);
else if (value?.Equals(DateTimeOffset.MinValue) == true) value = new DateTime(1970, 1, 1);
var ret = new OdbcParameter { ParameterName = $"@{name}", Value = value };
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) ret.OdbcType = (OdbcType)tp.Value;

View File

@ -73,7 +73,7 @@ namespace FreeSql.PostgreSQL
else if (param is TimeOnly || param is TimeOnly?)
{
var ts = (TimeOnly)param;
return $"'{ts.Hour}:{ts.Minute}:{ts.Second}.{ts.Millisecond}'";
return $"'{ts.Hour}:{ts.Minute}:{ts.Second}'";
}
#endif

View File

@ -47,7 +47,7 @@ namespace FreeSql.PostgreSQL
{ typeof(DateTime).FullName, CsToDb.New(NpgsqlDbType.Timestamp, "timestamp", "timestamp NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, CsToDb.New(NpgsqlDbType.Timestamp, "timestamp", "timestamp", false, true, null) },
#if net60
{ typeof(TimeOnly).FullName, CsToDb.New(NpgsqlDbType.Time, "time", "time NOT NULL", false, false, 0) },{ typeof(TimeOnly?).FullName, CsToDb.New(NpgsqlDbType.Time, "time", "time", false, true, null) },
{ typeof(TimeOnly).FullName, CsToDb.New(NpgsqlDbType.Time, "time", "time NOT NULL", false, false, TimeOnly.MinValue) },{ typeof(TimeOnly?).FullName, CsToDb.New(NpgsqlDbType.Time, "time", "time", false, true, null) },
{ typeof(DateOnly).FullName, CsToDb.New(NpgsqlDbType.Date, "date", "date NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateOnly?).FullName, CsToDb.New(NpgsqlDbType.Date, "date", "date", false, true, null) },
#endif

View File

@ -26,6 +26,10 @@ namespace FreeSql.PostgreSQL
{
if (Interlocked.Exchange(ref _firstInit, 0) == 1) //不能放在 static ctor .NetFramework 可能报初始化类型错误
{
#if net60
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(DateOnly)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(TimeOnly)] = true;
#endif
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(BigInteger)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(BitArray)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlPoint)] = true;

View File

@ -69,6 +69,12 @@ namespace FreeSql.PostgreSQL
} },
{ typeof((IPAddress Address, int Subnet)[]).FullName, a => getParamterArrayValue(typeof((IPAddress Address, int Subnet)), a, (IPAddress.Any, 0)) },
{ typeof((IPAddress Address, int Subnet)?[]).FullName, a => getParamterArrayValue(typeof((IPAddress Address, int Subnet)?), a, null) },
#if net60
{ typeof(DateOnly[]).FullName, a => getParamterArrayValue(typeof(DateTime), a, null) },
{ typeof(DateOnly?[]).FullName, a => getParamterArrayValue(typeof(DateTime?), a, null) },
{ typeof(TimeOnly[]).FullName, a => getParamterArrayValue(typeof(TimeSpan), a, null) },
{ typeof(TimeOnly?[]).FullName, a => getParamterArrayValue(typeof(TimeSpan?), a, null) },
#endif
};
static object getParamterValue(Type type, object value, int level = 0)
{
@ -87,6 +93,10 @@ namespace FreeSql.PostgreSQL
}
if (type.IsNullableType()) type = type.GenericTypeArguments.First();
if (type.IsEnum) return (int)value;
#if net60
if (type == typeof(DateOnly)) return ((DateOnly)value).ToDateTime(TimeOnly.MinValue);
if (type == typeof(TimeOnly)) return ((TimeOnly)value).ToTimeSpan();
#endif
if (dicGetParamterValue.TryGetValue(type.FullName, out var trydic)) return trydic(value);
return value;
}

View File

@ -90,15 +90,24 @@ namespace FreeSql.SqlServer
return string.Concat("'", ((DateTimeOffset)param).ToString("yyyy-MM-dd HH:mm:ss.fff zzzz"), "'");
}
#if net60
else if (param is DateOnly || param is DateOnly?)
else if (param is DateOnly)
{
var result = AddslashesTypeHandler(typeof(DateOnly), param);
if (result != null) return result;
if (param.Equals(DateOnly.MinValue) == true) param = new DateOnly(1970, 1, 1);
return string.Concat("'", ((DateOnly)param).ToString("yyyy-MM-dd"), "'");
}
else if (param is DateOnly?)
{
var result = AddslashesTypeHandler(typeof(DateOnly?), param);
if (result != null) return result;
if (param.Equals(DateOnly.MinValue) == true) param = new DateOnly(1970, 1, 1);
return string.Concat("'", ((DateOnly)param).ToString("yyyy-MM-dd"), "'");
}
else if (param is TimeOnly || param is TimeOnly?)
{
var ts = (TimeOnly)param;
return $"'{ts.Hour}:{ts.Minute}:{ts.Second}.{ts.Millisecond}'";
return $"'{ts.Hour}:{ts.Minute}:{ts.Second}'";
}
#endif
else if (param is TimeSpan || param is TimeSpan?)

View File

@ -38,7 +38,7 @@ namespace FreeSql.SqlServer
{ typeof(DateTime).FullName, CsToDb.New(SqlDbType.DateTime, "datetime", "datetime NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, CsToDb.New(SqlDbType.DateTime, "datetime", "datetime", false, true, null) },
{ typeof(DateTimeOffset).FullName, CsToDb.New(SqlDbType.DateTimeOffset, "datetimeoffset", "datetimeoffset NOT NULL", false, false, new DateTimeOffset(new DateTime(1970,1,1), TimeSpan.Zero)) },{ typeof(DateTimeOffset?).FullName, CsToDb.New(SqlDbType.DateTimeOffset, "datetimeoffset", "datetimeoffset", false, true, null) },
#if net60
{ typeof(TimeOnly).FullName, CsToDb.New(SqlDbType.Time, "time", "time NOT NULL", false, false, 0) },{ typeof(TimeOnly?).FullName, CsToDb.New(SqlDbType.Time, "time", "time", false, true, null) },
{ typeof(TimeOnly).FullName, CsToDb.New(SqlDbType.Time, "time", "time NOT NULL", false, false, TimeOnly.MinValue) },{ typeof(TimeOnly?).FullName, CsToDb.New(SqlDbType.Time, "time", "time", false, true, null) },
{ typeof(DateOnly).FullName, CsToDb.New(SqlDbType.Date, "date", "date NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateOnly?).FullName, CsToDb.New(SqlDbType.Date, "date", "date", false, true, null) },
#endif

View File

@ -1,4 +1,5 @@
using FreeSql.Internal.CommonProvider;
using FreeSql.Internal;
using FreeSql.Internal.CommonProvider;
using FreeSql.SqlServer.Curd;
using System;
using System.Data.Common;
@ -14,6 +15,10 @@ namespace FreeSql.SqlServer
{
if (Interlocked.Exchange(ref _firstInit, 0) == 1) //不能放在 static ctor .NetFramework 可能报初始化类型错误
{
#if net60
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(DateOnly)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(TimeOnly)] = true;
#endif
Select0Provider._dicMethodDataReaderGetValue[typeof(Guid)] = typeof(DbDataReader).GetMethod("GetGuid", new Type[] { typeof(int) });
}
}

View File

@ -30,6 +30,10 @@ namespace FreeSql.SqlServer
{
if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}";
if (value?.Equals(DateTime.MinValue) == true) value = new DateTime(1970, 1, 1);
else if (value?.Equals(DateTimeOffset.MinValue) == true) value = new DateTime(1970, 1, 1);
#if net60
else if (value?.Equals(DateOnly.MinValue) == true) value = new DateTime(1970, 1, 1);
#endif
var ret = new SqlParameter { ParameterName = QuoteParamterName(parameterName), Value = value };
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) ret.SqlDbType = (SqlDbType)tp.Value;
@ -52,6 +56,10 @@ namespace FreeSql.SqlServer
Utils.GetDbParamtersByObject<DbParameter>(sql, obj, "@", (name, type, value) =>
{
if (value?.Equals(DateTime.MinValue) == true) value = new DateTime(1970, 1, 1);
else if (value?.Equals(DateTimeOffset.MinValue) == true) value = new DateTime(1970, 1, 1);
#if net60
else if (value?.Equals(DateOnly.MinValue) == true) value = new DateTime(1970, 1, 1);
#endif
var ret = new SqlParameter { ParameterName = $"@{name}", Value = value };
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) ret.SqlDbType = (SqlDbType)tp.Value;

View File

@ -20,7 +20,7 @@ FreeSql is a powerful O/RM component, supports .NET Core 2.1+, .NET Framework 4.
- 🌲 Support expression functions, and customizable analysis.
- 🏁 Support one-to-many and many-to-many navigation properties, include and lazy loading.
- 📃 Support Read/Write separation, Splitting Table/Database, Global filters, Optimistic and pessimistic locker.
- 🌳 Support MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/南大通用/虚谷/神舟通用/翰高/ClickHouse/QuestDB/MsAccess, etc.
- 🌳 Support MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/南大通用/虚谷/神舟通用/翰高/ClickHouse/DuckDB/TDengine/QuestDB/MsAccess, etc.
QQ Groups**561616019(available)**、4336577(full)、8578575(full)、52508226(full)

View File

@ -20,24 +20,13 @@ FreeSql 是一款功能强大的对象关系映射O/RM组件支持 .NET
- ✒ 支持 丰富的表达式函数,以及灵活的自定义解析;
- 🏁 支持 导航属性一对多、多对多贪婪加载,以及延时加载;
- 📃 支持 读写分离、分表分库、过滤器、乐观锁、悲观锁;
- 🌳 支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/南大通用/虚谷/神舟通用/翰高/ClickHouse/QuestDB/Access 等数据库;
- 🌳 支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/南大通用/虚谷/神舟通用/翰高/ClickHouse/DuckDB/TDengine/QuestDB/Access 等数据库;
QQ群561616019(在线)、4336577(已满)、8578575(已满)、52508226(已满)
## 📚 文档
## 📚 文档开源(免费)
| | |
| - | - |
| <img src="https://github.com/dotnetcore/FreeSql/raw/master/Examples/restful/001.png" width="30" height="46"/> | [《新人学习指引》](https://www.cnblogs.com/FreeSql/p/11531300.html) \| [《Select》](https://github.com/2881099/FreeSql/wiki/%e6%9f%a5%e8%af%a2) \| [《Update》](https://github.com/2881099/FreeSql/wiki/%e4%bf%ae%e6%94%b9) \| [《Insert》](https://github.com/2881099/FreeSql/wiki/%e6%b7%bb%e5%8a%a0) \| [《Delete》](https://github.com/2881099/FreeSql/wiki/%e5%88%a0%e9%99%a4) |
| <img src="https://github.com/dotnetcore/FreeSql/raw/master/Examples/restful/002.png" width="30" height="46"/> | [《表达式函数》](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0) \| [《CodeFirst》](https://github.com/2881099/FreeSql/wiki/CodeFirst) \| [《DbFirst》](https://github.com/2881099/FreeSql/wiki/DbFirst) \| [《过滤器》](https://github.com/2881099/FreeSql/wiki/%e8%bf%87%e6%bb%a4%e5%99%a8) |
| <img src="https://github.com/dotnetcore/FreeSql/raw/master/Examples/restful/003.png" width="30" height="46"/> | [《Repository》](https://github.com/2881099/FreeSql/wiki/Repository) \| [《UnitOfWork》](https://github.com/2881099/FreeSql/wiki/%e5%b7%a5%e4%bd%9c%e5%8d%95%e5%85%83) \| [《DbContext》](https://github.com/2881099/FreeSql/wiki/DbContext) \| [《ADO》](https://github.com/2881099/FreeSql/wiki/ADO) \| [《AOP》](https://github.com/2881099/FreeSql/wiki/AOP) |
| <img src="https://github.com/dotnetcore/FreeSql/raw/master/Examples/restful/004.png" width="30" height="46"/> | [《读写分离》](https://github.com/2881099/FreeSql/wiki/%e8%af%bb%e5%86%99%e5%88%86%e7%a6%bb) \| [《分表分库》](https://github.com/2881099/FreeSql/wiki/%e5%88%86%e8%a1%a8%e5%88%86%e5%ba%93) \| [《黑科技》](https://github.com/2881099/FreeSql/wiki/%E9%AA%9A%E6%93%8D%E4%BD%9C) \| [《常见问题》](https://github.com/dotnetcore/FreeSql/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) \| [*更新日志*](https://github.com/2881099/FreeSql/wiki/%e6%9b%b4%e6%96%b0%e6%97%a5%e5%bf%97) |
> FreeSql 提供多种使用习惯,请根据实际情况选择团队合适的一种:
- 要么 FreeSql原始用法
- 要么 [FreeSql.DbContext](https://github.com/2881099/FreeSql/wiki/Repository),仓储+工作单元习惯;
- 要么 [FreeSql.BaseEntity](https://github.com/2881099/FreeSql/tree/master/Examples/base_entity),求简单使用这个;
[部署本地文档](https://github.com/2881099/FreeSql.Wiki.VuePress)、[在线文档](https://freesql.net)
> 示范项目