Repository: dotnet/efcore

Issue:
Correct SqliteType inference from string, DateOnly, TimeOnly
Microsoft.Data.Sqlite 6.0.1
TargetFramework net6.0-windows

当我创建一个字符串类型的SqliteParameter时，我查询它的类型，得到的类型信息是 “SqliteType.Integer”

```C#

var p = new Microsoft.Data.Sqlite.SqliteParameter("Name","123");

```

后来我在源码中定位到了以下位置，这就有点不合适了吧

https://github.com/dotnet/efcore/blob/8144d50ec0d15b87c35a9a3a425b1faadafb87f1/src/Microsoft.Data.Sqlite.Core/SqliteValueBinder.cs#L240-L263


Hints:
Google Translate:

```
When I create a SqliteParameter of type string, I query its type, and the type info I get is "SqliteType.Integer"
...
Later, I located the following location in the source code, which is a bit inappropriate.
```

/cc @bricelam 

Patch:
diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteParameter.cs b/src/Microsoft.Data.Sqlite.Core/SqliteParameter.cs
index 265634b0100..e71073b8300 100644
--- a/src/Microsoft.Data.Sqlite.Core/SqliteParameter.cs
+++ b/src/Microsoft.Data.Sqlite.Core/SqliteParameter.cs
@@ -200,7 +200,7 @@ public override void ResetDbType()
         public virtual void ResetSqliteType()
         {
             DbType = DbType.String;
-            SqliteType = SqliteType.Text;
+            _sqliteType = null;
         }
 
         internal bool Bind(sqlite3_stmt stmt)
diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteValueBinder.cs b/src/Microsoft.Data.Sqlite.Core/SqliteValueBinder.cs
index 3e7ac998b8a..137a50fe080 100644
--- a/src/Microsoft.Data.Sqlite.Core/SqliteValueBinder.cs
+++ b/src/Microsoft.Data.Sqlite.Core/SqliteValueBinder.cs
@@ -246,6 +246,10 @@ public virtual void Bind()
                 { typeof(char), SqliteType.Text },
                 { typeof(DateTime), SqliteType.Text },
                 { typeof(DateTimeOffset), SqliteType.Text },
+#if NET6_0_OR_GREATER
+                { typeof(DateOnly), SqliteType.Text },
+                { typeof(TimeOnly), SqliteType.Text },
+#endif
                 { typeof(DBNull), SqliteType.Text },
                 { typeof(decimal), SqliteType.Text },
                 { typeof(double), SqliteType.Real },
@@ -255,7 +259,7 @@ public virtual void Bind()
                 { typeof(long), SqliteType.Integer },
                 { typeof(sbyte), SqliteType.Integer },
                 { typeof(short), SqliteType.Integer },
-                { typeof(string), SqliteType.Integer },
+                { typeof(string), SqliteType.Text },
                 { typeof(TimeSpan), SqliteType.Text },
                 { typeof(uint), SqliteType.Integer },
                 { typeof(ulong), SqliteType.Integer },


Test patch:
diff --git a/test/Microsoft.Data.Sqlite.Tests/SqliteParameterTest.cs b/test/Microsoft.Data.Sqlite.Tests/SqliteParameterTest.cs
index 1779cad3e0b..e7758f21dac 100644
--- a/test/Microsoft.Data.Sqlite.Tests/SqliteParameterTest.cs
+++ b/test/Microsoft.Data.Sqlite.Tests/SqliteParameterTest.cs
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
+using System.Collections.Generic;
 using System.Data;
 using System.Data.Common;
 using Microsoft.Data.Sqlite.Properties;
@@ -93,6 +94,21 @@ public void SqliteType_defaults_to_text()
             Assert.Equal(SqliteType.Text, new SqliteParameter().SqliteType);
         }
 
+        [Theory]
+        [MemberData(nameof(TypesData))]
+        public void SqliteType_is_inferred_from_value(object value, SqliteType expectedType)
+        {
+            var parameter = new SqliteParameter { Value = value };
+            Assert.Equal(expectedType, parameter.SqliteType);
+        }
+
+        [Fact]
+        public void SqliteType_overrides_inferred_value()
+        {
+            var parameter = new SqliteParameter { Value = 'A', SqliteType = SqliteType.Integer };
+            Assert.Equal(SqliteType.Integer, parameter.SqliteType);
+        }
+
         [Fact]
         public void Direction_input_by_default()
         {
@@ -128,6 +144,16 @@ public void ResetSqliteType_works()
             Assert.Equal(SqliteType.Text, parameter.SqliteType);
         }
 
+        [Fact]
+        public void ResetSqliteType_works_when_value()
+        {
+            var parameter = new SqliteParameter { Value = new byte[0], SqliteType = SqliteType.Text };
+
+            parameter.ResetSqliteType();
+
+            Assert.Equal(SqliteType.Blob, parameter.SqliteType);
+        }
+
         [Fact]
         public void Bind_requires_set_name()
         {
@@ -557,6 +583,36 @@ public void Add_range_of_parameters_using_DbCommand_base_class()
             }
         }
 
+        public static IEnumerable<object[]> TypesData
+        => new List<object[]>
+        {
+            new object[] { default(DateTime), SqliteType.Text },
+            new object[] { default(DateTimeOffset), SqliteType.Text },
+            new object[] { DBNull.Value, SqliteType.Text },
+            new object[] { 0m, SqliteType.Text },
+            new object[] { default(Guid), SqliteType.Text },
+            new object[] { default(TimeSpan), SqliteType.Text },
+            new object[] { default(TimeSpan), SqliteType.Text },
+#if NET6_0_OR_GREATER
+            new object[] { default(DateOnly), SqliteType.Text },
+            new object[] { default(TimeOnly), SqliteType.Text },
+#endif
+            new object[] { 'A', SqliteType.Text },
+            new object[] { "", SqliteType.Text },
+            new object[] { false, SqliteType.Integer },
+            new object[] { (byte)0, SqliteType.Integer },
+            new object[] { 0, SqliteType.Integer },
+            new object[] { 0L, SqliteType.Integer },
+            new object[] { (sbyte)0, SqliteType.Integer },
+            new object[] { (short)0, SqliteType.Integer },
+            new object[] { 0u, SqliteType.Integer },
+            new object[] { 0ul, SqliteType.Integer },
+            new object[] { (ushort)0, SqliteType.Integer },
+            new object[] { 0.0, SqliteType.Real },
+            new object[] { 0f, SqliteType.Real },
+            new object[] { new byte[0], SqliteType.Blob },
+        };
+
         private enum MyEnum
         {
             One = 1