Commit a9560b31 authored by Sergii Volchkov's avatar Sergii Volchkov Committed by Nick Craver

Enable SqlDataRecord TVPs on netstandard1.3. (#802)

* Enable SqlDataRecord TVPs on netstandard1.3.
* Update netstandard2.0 SqlClient references to Preview 2.
* Skip TransactionScope tests for netcoreapp2.0.
- According to https://github.com/dotnet/corefx/issues/12534, ambient transaction enlistment is not included with .net core 2.0.
* Update references in Dapper.StrongName.
* Disable parallel test run to stabilize flaky type handler tests.
* Disable parallel test run by assembly attribute.
* Move Issue461 tests to TypeHandlerTests.
* Group type handler tests in a collection, re-enable parallelization.
- Being part of the same collection, type handler tests will run sequentially. All other tests can run in parallel.
* Move tests relying on query cache & type maps to a separate collection.
parent 910246bf
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' "> <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="System.Collections.Concurrent" Version="4.3.0" /> <PackageReference Include="System.Collections.Concurrent" Version="4.3.0" />
<PackageReference Include="System.Collections.NonGeneric" Version="4.3.0" /> <PackageReference Include="System.Collections.NonGeneric" Version="4.3.0" />
<PackageReference Include="System.Data.Common" Version="4.3.0" /> <PackageReference Include="System.Data.SqlClient" Version="4.3.0" />
<PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" /> <PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" /> <PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" /> <PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" />
...@@ -31,7 +31,8 @@ ...@@ -31,7 +31,8 @@
<PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" /> <PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' "> <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Data.SqlClient" Version="4.4.0-preview1-25305-02" /> <PackageReference Include="System.Data.Common" Version="4.3.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.4.0-preview2-25405-01" />
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" /> <PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" /> <PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" />
</ItemGroup> </ItemGroup>
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
<PackageReference Include="Microsoft.Data.Sqlite" Version="1.1.0" /> <PackageReference Include="Microsoft.Data.Sqlite" Version="1.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="MySql.Data" Version="7.0.7-m61" /> <PackageReference Include="MySql.Data" Version="7.0.7-m61" />
<PackageReference Include="System.Data.SqlClient" Version="4.4.0-preview1-25305-02" /> <PackageReference Include="System.Data.SqlClient" Version="4.4.0-preview2-25405-01" />
<PackageReference Include="xunit" Version="2.3.0-beta1-build3642" /> <PackageReference Include="xunit" Version="2.3.0-beta1-build3642" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta1-build1309" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta1-build1309" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.0-beta1-build3642" /> <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.0-beta1-build3642" />
......
...@@ -5,10 +5,8 @@ ...@@ -5,10 +5,8 @@
using Dapper.Contrib.Extensions; using Dapper.Contrib.Extensions;
#if !NETCOREAPP1_0
using System.Transactions;
#endif
#if !NETCOREAPP1_0 && !NETCOREAPP2_0 #if !NETCOREAPP1_0 && !NETCOREAPP2_0
using System.Transactions;
using System.Data.SqlServerCe; using System.Data.SqlServerCe;
#endif #endif
using FactAttribute = Dapper.Tests.Contrib.SkippableFactAttribute; using FactAttribute = Dapper.Tests.Contrib.SkippableFactAttribute;
...@@ -527,7 +525,7 @@ public void Transactions() ...@@ -527,7 +525,7 @@ public void Transactions()
} }
} }
#if !NETCOREAPP1_0 #if !NETCOREAPP1_0 && !NETCOREAPP2_0
[Fact] [Fact]
public void TransactionScope() public void TransactionScope()
{ {
......
...@@ -353,28 +353,35 @@ public void RunSequentialVersusParallelSync() ...@@ -353,28 +353,35 @@ public void RunSequentialVersusParallelSync()
Console.WriteLine("Pipeline: {0}ms", watch.ElapsedMilliseconds); Console.WriteLine("Pipeline: {0}ms", watch.ElapsedMilliseconds);
} }
[Fact] [Collection("QueryCacheTests")]
public void AssertNoCacheWorksForQueryMultiple() public class AsyncQueryCacheTests : TestBase
{ {
const int a = 123, b = 456; private SqlConnection _marsConnection;
var cmdDef = new CommandDefinition(@"select @a; select @b;", new private SqlConnection MarsConnection => _marsConnection ?? (_marsConnection = GetOpenConnection(true));
{
a, b
}, commandType: CommandType.Text, flags: CommandFlags.NoCache);
int c, d; [Fact]
SqlMapper.PurgeQueryCache(); public void AssertNoCacheWorksForQueryMultiple()
int before = SqlMapper.GetCachedSQLCount();
using (var multi = MarsConnection.QueryMultiple(cmdDef))
{ {
c = multi.Read<int>().Single(); const int a = 123, b = 456;
d = multi.Read<int>().Single(); var cmdDef = new CommandDefinition(@"select @a; select @b;", new
{
a, b
}, commandType: CommandType.Text, flags: CommandFlags.NoCache);
int c, d;
SqlMapper.PurgeQueryCache();
int before = SqlMapper.GetCachedSQLCount();
using (var multi = MarsConnection.QueryMultiple(cmdDef))
{
c = multi.Read<int>().Single();
d = multi.Read<int>().Single();
}
int after = SqlMapper.GetCachedSQLCount();
before.IsEqualTo(0);
after.IsEqualTo(0);
c.IsEqualTo(123);
d.IsEqualTo(456);
} }
int after = SqlMapper.GetCachedSQLCount();
before.IsEqualTo(0);
after.IsEqualTo(0);
c.IsEqualTo(123);
d.IsEqualTo(456);
} }
private class BasicType private class BasicType
......
...@@ -104,85 +104,6 @@ public bool GetWentThroughProperConstructor() ...@@ -104,85 +104,6 @@ public bool GetWentThroughProperConstructor()
} }
} }
[Fact]
public void Issue461_TypeHandlerWorksInConstructor()
{
SqlMapper.AddTypeHandler(new Issue461_BlargHandler());
connection.Execute(@"CREATE TABLE #Issue461 (
Id int not null IDENTITY(1,1),
SomeValue nvarchar(50),
SomeBlargValue nvarchar(200),
)");
const string Expected = "abc123def";
var blarg = new Blarg(Expected);
connection.Execute(
"INSERT INTO #Issue461 (SomeValue, SomeBlargValue) VALUES (@value, @blarg)",
new { value = "what up?", blarg });
// test: without constructor
var parameterlessWorks = connection.QuerySingle<Issue461_ParameterlessTypeConstructor>("SELECT * FROM #Issue461");
parameterlessWorks.Id.IsEqualTo(1);
parameterlessWorks.SomeValue.IsEqualTo("what up?");
parameterlessWorks.SomeBlargValue.Value.IsEqualTo(Expected);
// test: via constructor
var parameterDoesNot = connection.QuerySingle<Issue461_ParameterisedTypeConstructor>("SELECT * FROM #Issue461");
parameterDoesNot.Id.IsEqualTo(1);
parameterDoesNot.SomeValue.IsEqualTo("what up?");
parameterDoesNot.SomeBlargValue.Value.IsEqualTo(Expected);
}
// I would usually expect this to be a struct; using a class
// so that we can't pass unexpectedly due to forcing an unsafe cast - want
// to see an InvalidCastException if it is wrong
private class Blarg
{
public Blarg(string value) { Value = value; }
public string Value { get; }
public override string ToString()
{
return Value;
}
}
private class Issue461_BlargHandler : SqlMapper.TypeHandler<Blarg>
{
public override void SetValue(IDbDataParameter parameter, Blarg value)
{
parameter.Value = ((object)value.Value) ?? DBNull.Value;
}
public override Blarg Parse(object value)
{
string s = (value == null || value is DBNull) ? null : Convert.ToString(value);
return new Blarg(s);
}
}
private class Issue461_ParameterlessTypeConstructor
{
public int Id { get; set; }
public string SomeValue { get; set; }
public Blarg SomeBlargValue { get; set; }
}
private class Issue461_ParameterisedTypeConstructor
{
public Issue461_ParameterisedTypeConstructor(int id, string someValue, Blarg someBlargValue)
{
Id = id;
SomeValue = someValue;
SomeBlargValue = someBlargValue;
}
public int Id { get; }
public string SomeValue { get; }
public Blarg SomeBlargValue { get; }
}
public static class AbstractInheritance public static class AbstractInheritance
{ {
public abstract class Order public abstract class Order
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="MySql.Data" Version="7.0.7-m61" /> <PackageReference Include="MySql.Data" Version="7.0.7-m61" />
<PackageReference Include="Npgsql" Version="3.2.2" /> <PackageReference Include="Npgsql" Version="3.2.2" />
<PackageReference Include="System.Data.SqlClient" Version="4.4.0-preview1-25305-02" /> <PackageReference Include="System.Data.SqlClient" Version="4.4.0-preview2-25405-01" />
<PackageReference Include="System.ValueTuple" Version="4.3.0" /> <PackageReference Include="System.ValueTuple" Version="4.3.0" />
<PackageReference Include="xunit" Version="2.3.0-beta1-build3642" /> <PackageReference Include="xunit" Version="2.3.0-beta1-build3642" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta1-build1309" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta1-build1309" />
......
...@@ -6,36 +6,40 @@ namespace Dapper.Tests ...@@ -6,36 +6,40 @@ namespace Dapper.Tests
{ {
public partial class DataReaderTests : TestBase public partial class DataReaderTests : TestBase
{ {
[Fact] [Collection("QueryCacheTests")]
public void GetSameReaderForSameShape() public class DataReaderQueryCacheTests : TestBase
{ {
var origReader = connection.ExecuteReader("select 'abc' as Name, 123 as Id"); [Fact]
var origParser = origReader.GetRowParser(typeof(HazNameId)); public void GetSameReaderForSameShape()
{
var origReader = connection.ExecuteReader("select 'abc' as Name, 123 as Id");
var origParser = origReader.GetRowParser(typeof(HazNameId));
var typedParser = origReader.GetRowParser<HazNameId>(); var typedParser = origReader.GetRowParser<HazNameId>();
ReferenceEquals(origParser, typedParser).IsEqualTo(true); ReferenceEquals(origParser, typedParser).IsEqualTo(true);
var list = origReader.Parse<HazNameId>().ToList(); var list = origReader.Parse<HazNameId>().ToList();
list.Count.IsEqualTo(1); list.Count.IsEqualTo(1);
list[0].Name.IsEqualTo("abc"); list[0].Name.IsEqualTo("abc");
list[0].Id.IsEqualTo(123); list[0].Id.IsEqualTo(123);
origReader.Dispose(); origReader.Dispose();
var secondReader = connection.ExecuteReader("select 'abc' as Name, 123 as Id"); var secondReader = connection.ExecuteReader("select 'abc' as Name, 123 as Id");
var secondParser = secondReader.GetRowParser(typeof(HazNameId)); var secondParser = secondReader.GetRowParser(typeof(HazNameId));
var thirdParser = secondReader.GetRowParser(typeof(HazNameId), 1); var thirdParser = secondReader.GetRowParser(typeof(HazNameId), 1);
list = secondReader.Parse<HazNameId>().ToList(); list = secondReader.Parse<HazNameId>().ToList();
list.Count.IsEqualTo(1); list.Count.IsEqualTo(1);
list[0].Name.IsEqualTo("abc"); list[0].Name.IsEqualTo("abc");
list[0].Id.IsEqualTo(123); list[0].Id.IsEqualTo(123);
secondReader.Dispose(); secondReader.Dispose();
// now: should be different readers, but same parser // now: should be different readers, but same parser
ReferenceEquals(origReader, secondReader).IsEqualTo(false); ReferenceEquals(origReader, secondReader).IsEqualTo(false);
ReferenceEquals(origParser, secondParser).IsEqualTo(true); ReferenceEquals(origParser, secondParser).IsEqualTo(true);
ReferenceEquals(secondParser, thirdParser).IsEqualTo(false); ReferenceEquals(secondParser, thirdParser).IsEqualTo(false);
}
} }
[Fact] [Fact]
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
using System.Linq; using System.Linq;
namespace Dapper.Tests namespace Dapper.Tests
{ {
[Collection("QueryCacheTests")]
public class NullTests : TestBase public class NullTests : TestBase
{ {
[Fact] [Fact]
......
...@@ -38,6 +38,24 @@ void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, SqlMapper.Id ...@@ -38,6 +38,24 @@ void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, SqlMapper.Id
} }
} }
private static List<Microsoft.SqlServer.Server.SqlDataRecord> CreateSqlDataRecordList(IEnumerable<int> numbers)
{
var number_list = new List<Microsoft.SqlServer.Server.SqlDataRecord>();
// Create an SqlMetaData object that describes our table type.
Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) };
foreach (int n in numbers)
{
// Create a new record, using the metadata array above.
var rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition);
rec.SetInt32(0, n); // Set the value.
number_list.Add(rec); // Add it to the list.
}
return number_list;
}
private class IntDynamicParam : SqlMapper.IDynamicParameters private class IntDynamicParam : SqlMapper.IDynamicParameters
{ {
private readonly IEnumerable<int> numbers; private readonly IEnumerable<int> numbers;
...@@ -51,19 +69,8 @@ public void AddParameters(IDbCommand command, SqlMapper.Identity identity) ...@@ -51,19 +69,8 @@ public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
var sqlCommand = (SqlCommand)command; var sqlCommand = (SqlCommand)command;
sqlCommand.CommandType = CommandType.StoredProcedure; sqlCommand.CommandType = CommandType.StoredProcedure;
var number_list = new List<Microsoft.SqlServer.Server.SqlDataRecord>(); var number_list = CreateSqlDataRecordList(numbers);
// Create an SqlMetaData object that describes our table type.
Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) };
foreach (int n in numbers)
{
// Create a new record, using the metadata array above.
var rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition);
rec.SetInt32(0, n); // Set the value.
number_list.Add(rec); // Add it to the list.
}
// Add the table parameter. // Add the table parameter.
var p = sqlCommand.Parameters.Add("ints", SqlDbType.Structured); var p = sqlCommand.Parameters.Add("ints", SqlDbType.Structured);
p.Direction = ParameterDirection.Input; p.Direction = ParameterDirection.Input;
...@@ -85,19 +92,8 @@ public void AddParameter(IDbCommand command, string name) ...@@ -85,19 +92,8 @@ public void AddParameter(IDbCommand command, string name)
var sqlCommand = (SqlCommand)command; var sqlCommand = (SqlCommand)command;
sqlCommand.CommandType = CommandType.StoredProcedure; sqlCommand.CommandType = CommandType.StoredProcedure;
var number_list = new List<Microsoft.SqlServer.Server.SqlDataRecord>(); var number_list = CreateSqlDataRecordList(numbers);
// Create an SqlMetaData object that describes our table type.
Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) };
foreach (int n in numbers)
{
// Create a new record, using the metadata array above.
var rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition);
rec.SetInt32(0, n); // Set the value.
number_list.Add(rec); // Add it to the list.
}
// Add the table parameter. // Add the table parameter.
var p = sqlCommand.Parameters.Add(name, SqlDbType.Structured); var p = sqlCommand.Parameters.Add(name, SqlDbType.Structured);
p.Direction = ParameterDirection.Input; p.Direction = ParameterDirection.Input;
...@@ -218,7 +214,6 @@ public void TestMassiveStrings() ...@@ -218,7 +214,6 @@ public void TestMassiveStrings()
.IsEqualTo(str); .IsEqualTo(str);
} }
#if !NETCOREAPP1_0
[Fact] [Fact]
public void TestTVPWithAnonymousObject() public void TestTVPWithAnonymousObject()
{ {
...@@ -289,19 +284,8 @@ public new void AddParameters(IDbCommand command, SqlMapper.Identity identity) ...@@ -289,19 +284,8 @@ public new void AddParameters(IDbCommand command, SqlMapper.Identity identity)
var sqlCommand = (SqlCommand)command; var sqlCommand = (SqlCommand)command;
sqlCommand.CommandType = CommandType.StoredProcedure; sqlCommand.CommandType = CommandType.StoredProcedure;
var number_list = new List<Microsoft.SqlServer.Server.SqlDataRecord>(); var number_list = CreateSqlDataRecordList(numbers);
// Create an SqlMetaData object that describes our table type.
Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) };
foreach (int n in numbers)
{
// Create a new record, using the metadata array above.
var rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition);
rec.SetInt32(0, n); // Set the value.
number_list.Add(rec); // Add it to the list.
}
// Add the table parameter. // Add the table parameter.
var p = sqlCommand.Parameters.Add("ints", SqlDbType.Structured); var p = sqlCommand.Parameters.Add("ints", SqlDbType.Structured);
p.Direction = ParameterDirection.Input; p.Direction = ParameterDirection.Input;
...@@ -344,6 +328,83 @@ public void TestTVPWithAdditionalParams() ...@@ -344,6 +328,83 @@ public void TestTVPWithAdditionalParams()
} }
} }
[Fact]
public void TestSqlDataRecordListParametersWithAsTableValuedParameter()
{
try
{
connection.Execute("CREATE TYPE int_list_type AS TABLE (n int NOT NULL PRIMARY KEY)");
connection.Execute("CREATE PROC get_ints @integers int_list_type READONLY AS select * from @integers");
var records = CreateSqlDataRecordList(new int[] { 1, 2, 3 });
var nums = connection.Query<int>("get_ints", new { integers = records.AsTableValuedParameter() }, commandType: CommandType.StoredProcedure).ToList();
nums.IsSequenceEqualTo(new int[] { 1, 2, 3 });
nums = connection.Query<int>("select * from @integers", new { integers = records.AsTableValuedParameter("int_list_type") }).ToList();
nums.IsSequenceEqualTo(new int[] { 1, 2, 3 });
try
{
connection.Query<int>("select * from @integers", new { integers = records.AsTableValuedParameter() }).First();
throw new InvalidOperationException();
}
catch (Exception ex)
{
ex.Message.Equals("The table type parameter 'ids' must have a valid type name.");
}
}
finally
{
try
{
connection.Execute("DROP PROC get_ints");
}
finally
{
connection.Execute("DROP TYPE int_list_type");
}
}
}
[Fact]
public void TestSqlDataRecordListParametersWithTypeHandlers()
{
try
{
connection.Execute("CREATE TYPE int_list_type AS TABLE (n int NOT NULL PRIMARY KEY)");
connection.Execute("CREATE PROC get_ints @integers int_list_type READONLY AS select * from @integers");
// Variable type has to be IEnumerable<SqlDataRecord> for TypeHandler to kick in.
IEnumerable<Microsoft.SqlServer.Server.SqlDataRecord> records = CreateSqlDataRecordList(new int[] { 1, 2, 3 });
var nums = connection.Query<int>("get_ints", new { integers = records }, commandType: CommandType.StoredProcedure).ToList();
nums.IsSequenceEqualTo(new int[] { 1, 2, 3 });
try
{
connection.Query<int>("select * from @integers", new { integers = records }).First();
throw new InvalidOperationException();
}
catch (Exception ex)
{
ex.Message.Equals("The table type parameter 'ids' must have a valid type name.");
}
}
finally
{
try
{
connection.Execute("DROP PROC get_ints");
}
finally
{
connection.Execute("DROP TYPE int_list_type");
}
}
}
#if !NETCOREAPP1_0
[Fact] [Fact]
public void DataTableParameters() public void DataTableParameters()
{ {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
namespace Dapper.Tests.Providers namespace Dapper.Tests.Providers
{ {
[Collection("TypeHandlerTests")]
public class EntityFrameworkTests : TestBase public class EntityFrameworkTests : TestBase
{ {
public EntityFrameworkTests() public EntityFrameworkTests()
......
...@@ -24,41 +24,45 @@ public void DapperEnumValue_Sqlite() ...@@ -24,41 +24,45 @@ public void DapperEnumValue_Sqlite()
} }
} }
[FactSqlite] [Collection("TypeHandlerTests")]
public void Issue466_SqliteHatesOptimizations() public class SqliteTypeHandlerTests : TestBase
{ {
using (var connection = GetSQLiteConnection()) [FactSqlite]
public void Issue466_SqliteHatesOptimizations()
{ {
SqlMapper.ResetTypeHandlers(); using (var connection = GetSQLiteConnection())
var row = connection.Query<HazNameId>("select 42 as Id").First(); {
row.Id.IsEqualTo(42); SqlMapper.ResetTypeHandlers();
row = connection.Query<HazNameId>("select 42 as Id").First(); var row = connection.Query<HazNameId>("select 42 as Id").First();
row.Id.IsEqualTo(42); row.Id.IsEqualTo(42);
row = connection.Query<HazNameId>("select 42 as Id").First();
row.Id.IsEqualTo(42);
SqlMapper.ResetTypeHandlers(); SqlMapper.ResetTypeHandlers();
row = connection.QueryFirst<HazNameId>("select 42 as Id"); row = connection.QueryFirst<HazNameId>("select 42 as Id");
row.Id.IsEqualTo(42); row.Id.IsEqualTo(42);
row = connection.QueryFirst<HazNameId>("select 42 as Id"); row = connection.QueryFirst<HazNameId>("select 42 as Id");
row.Id.IsEqualTo(42); row.Id.IsEqualTo(42);
}
} }
}
[FactSqlite] [FactSqlite]
public async Task Issue466_SqliteHatesOptimizations_Async() public async Task Issue466_SqliteHatesOptimizations_Async()
{
using (var connection = GetSQLiteConnection())
{ {
SqlMapper.ResetTypeHandlers(); using (var connection = GetSQLiteConnection())
var row = (await connection.QueryAsync<HazNameId>("select 42 as Id").ConfigureAwait(false)).First(); {
row.Id.IsEqualTo(42); SqlMapper.ResetTypeHandlers();
row = (await connection.QueryAsync<HazNameId>("select 42 as Id").ConfigureAwait(false)).First(); var row = (await connection.QueryAsync<HazNameId>("select 42 as Id").ConfigureAwait(false)).First();
row.Id.IsEqualTo(42); row.Id.IsEqualTo(42);
row = (await connection.QueryAsync<HazNameId>("select 42 as Id").ConfigureAwait(false)).First();
row.Id.IsEqualTo(42);
SqlMapper.ResetTypeHandlers(); SqlMapper.ResetTypeHandlers();
row = await connection.QueryFirstAsync<HazNameId>("select 42 as Id").ConfigureAwait(false); row = await connection.QueryFirstAsync<HazNameId>("select 42 as Id").ConfigureAwait(false);
row.Id.IsEqualTo(42); row.Id.IsEqualTo(42);
row = await connection.QueryFirstAsync<HazNameId>("select 42 as Id").ConfigureAwait(false); row = await connection.QueryFirstAsync<HazNameId>("select 42 as Id").ConfigureAwait(false);
row.Id.IsEqualTo(42); row.Id.IsEqualTo(42);
}
} }
} }
......
This diff is collapsed.
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' "> <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="System.Collections.Concurrent" Version="4.3.0" /> <PackageReference Include="System.Collections.Concurrent" Version="4.3.0" />
<PackageReference Include="System.Collections.NonGeneric" Version="4.3.0" /> <PackageReference Include="System.Collections.NonGeneric" Version="4.3.0" />
<PackageReference Include="System.Data.Common" Version="4.3.0" /> <PackageReference Include="System.Data.SqlClient" Version="4.3.0" />
<PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" /> <PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" /> <PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" /> <PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" />
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
<PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" /> <PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' "> <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Data.SqlClient" Version="4.4.0-preview1-25305-02" /> <PackageReference Include="System.Data.Common" Version="4.3.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.4.0-preview2-25405-01" />
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" /> <PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" /> <PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" />
</ItemGroup> </ItemGroup>
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
#if !NETSTANDARD1_3
namespace Dapper namespace Dapper
{ {
internal sealed class SqlDataRecordHandler : SqlMapper.ITypeHandler internal sealed class SqlDataRecordHandler : SqlMapper.ITypeHandler
...@@ -18,4 +17,3 @@ public void SetValue(IDbDataParameter parameter, object value) ...@@ -18,4 +17,3 @@ public void SetValue(IDbDataParameter parameter, object value)
} }
} }
} }
#endif
\ No newline at end of file
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Reflection;
#if !NETSTANDARD1_3
namespace Dapper namespace Dapper
{ {
/// <summary> /// <summary>
...@@ -23,18 +22,6 @@ public SqlDataRecordListTVPParameter(IEnumerable<Microsoft.SqlServer.Server.SqlD ...@@ -23,18 +22,6 @@ public SqlDataRecordListTVPParameter(IEnumerable<Microsoft.SqlServer.Server.SqlD
this.typeName = typeName; this.typeName = typeName;
} }
private static readonly Action<System.Data.SqlClient.SqlParameter, string> setTypeName;
static SqlDataRecordListTVPParameter()
{
var prop = typeof(System.Data.SqlClient.SqlParameter).GetProperty(nameof(System.Data.SqlClient.SqlParameter.TypeName), BindingFlags.Instance | BindingFlags.Public);
if (prop != null && prop.PropertyType == typeof(string) && prop.CanWrite)
{
setTypeName = (Action<System.Data.SqlClient.SqlParameter, string>)
Delegate.CreateDelegate(typeof(Action<System.Data.SqlClient.SqlParameter, string>), prop.GetSetMethod());
}
}
void SqlMapper.ICustomQueryParameter.AddParameter(IDbCommand command, string name) void SqlMapper.ICustomQueryParameter.AddParameter(IDbCommand command, string name)
{ {
var param = command.CreateParameter(); var param = command.CreateParameter();
...@@ -54,4 +41,3 @@ internal static void Set(IDbDataParameter parameter, IEnumerable<Microsoft.SqlSe ...@@ -54,4 +41,3 @@ internal static void Set(IDbDataParameter parameter, IEnumerable<Microsoft.SqlSe
} }
} }
} }
#endif
\ No newline at end of file
...@@ -219,24 +219,22 @@ private static void ResetTypeHandlers(bool clone) ...@@ -219,24 +219,22 @@ private static void ResetTypeHandlers(bool clone)
typeHandlers = new Dictionary<Type, ITypeHandler>(); typeHandlers = new Dictionary<Type, ITypeHandler>();
#if !NETSTANDARD1_3 #if !NETSTANDARD1_3
AddTypeHandlerImpl(typeof(DataTable), new DataTableHandler(), clone); AddTypeHandlerImpl(typeof(DataTable), new DataTableHandler(), clone);
#endif
try try
{ {
AddSqlDataRecordsTypeHandler(clone); AddSqlDataRecordsTypeHandler(clone);
} }
catch { /* https://github.com/StackExchange/dapper-dot-net/issues/424 */ } catch { /* https://github.com/StackExchange/dapper-dot-net/issues/424 */ }
#endif
AddTypeHandlerImpl(typeof(XmlDocument), new XmlDocumentHandler(), clone); AddTypeHandlerImpl(typeof(XmlDocument), new XmlDocumentHandler(), clone);
AddTypeHandlerImpl(typeof(XDocument), new XDocumentHandler(), clone); AddTypeHandlerImpl(typeof(XDocument), new XDocumentHandler(), clone);
AddTypeHandlerImpl(typeof(XElement), new XElementHandler(), clone); AddTypeHandlerImpl(typeof(XElement), new XElementHandler(), clone);
} }
#if !NETSTANDARD1_3
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
private static void AddSqlDataRecordsTypeHandler(bool clone) private static void AddSqlDataRecordsTypeHandler(bool clone)
{ {
AddTypeHandlerImpl(typeof(IEnumerable<Microsoft.SqlServer.Server.SqlDataRecord>), new SqlDataRecordHandler(), clone); AddTypeHandlerImpl(typeof(IEnumerable<Microsoft.SqlServer.Server.SqlDataRecord>), new SqlDataRecordHandler(), clone);
} }
#endif
/// <summary> /// <summary>
/// Configure the specified type to be mapped to a given db-type. /// Configure the specified type to be mapped to a given db-type.
...@@ -3662,15 +3660,15 @@ public static void SetTypeName(this DataTable table, string typeName) ...@@ -3662,15 +3660,15 @@ public static void SetTypeName(this DataTable table, string typeName)
/// <param name="table">The <see cref="DataTable"/> that has a type name associated with it.</param> /// <param name="table">The <see cref="DataTable"/> that has a type name associated with it.</param>
public static string GetTypeName(this DataTable table) => public static string GetTypeName(this DataTable table) =>
table?.ExtendedProperties[DataTableTypeNameKey] as string; table?.ExtendedProperties[DataTableTypeNameKey] as string;
#endif
/// <summary> /// <summary>
/// Used to pass a IEnumerable&lt;SqlDataRecord&gt; as a <see cref="TableValuedParameter"/>. /// Used to pass a IEnumerable&lt;SqlDataRecord&gt; as a TableValuedParameter.
/// </summary> /// </summary>
/// <param name="list">Thhe list of records to convert to TVPs.</param> /// <param name="list">The list of records to convert to TVPs.</param>
/// <param name="typeName">The sql parameter type name.</param> /// <param name="typeName">The sql parameter type name.</param>
public static ICustomQueryParameter AsTableValuedParameter(this IEnumerable<Microsoft.SqlServer.Server.SqlDataRecord> list, string typeName = null) => public static ICustomQueryParameter AsTableValuedParameter(this IEnumerable<Microsoft.SqlServer.Server.SqlDataRecord> list, string typeName = null) =>
new SqlDataRecordListTVPParameter(list, typeName); new SqlDataRecordListTVPParameter(list, typeName);
#endif
// one per thread // one per thread
[ThreadStatic] [ThreadStatic]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment