diff --git a/Directory.Packages.props b/Directory.Packages.props index afb6ea35..70b50470 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,32 +6,34 @@ - + + + + + + + + + - - - - - - \ No newline at end of file diff --git a/test/Dapper.AOT.Test/Dapper.AOT.Test.csproj b/test/Dapper.AOT.Test/Dapper.AOT.Test.csproj index e19c9662..68d37e5d 100644 --- a/test/Dapper.AOT.Test/Dapper.AOT.Test.csproj +++ b/test/Dapper.AOT.Test/Dapper.AOT.Test.csproj @@ -32,6 +32,7 @@ + @@ -52,5 +53,6 @@ + diff --git a/test/Dapper.AOT.Test/Integration/BatchPostgresql.cs b/test/Dapper.AOT.Test/Integration/BatchPostgresql.cs new file mode 100644 index 00000000..55fb266c --- /dev/null +++ b/test/Dapper.AOT.Test/Integration/BatchPostgresql.cs @@ -0,0 +1,74 @@ +using System.Data; +using System.Linq; +using Xunit; + +namespace Dapper.AOT.Test.Integration; + +[Collection(SharedPostgresqlClient.Collection)] +public class BatchPostgresql +{ + private PostgresqlFixture _fixture; + + public BatchPostgresql(PostgresqlFixture fixture) + { + _fixture = fixture; + fixture.NpgsqlConnection.Execute(""" + CREATE TABLE IF NOT EXISTS batch_exec( + id integer PRIMARY KEY, + name varchar(40) NOT NULL CHECK (name <> '') + ); + TRUNCATE batch_exec; + """); + } + + [Fact] + public void ExecuteMulti() + { + var items = Enumerable.Range(0, 100).Select(i => (i, $"item {i}")).ToList(); + var count = _fixture.NpgsqlConnection.Command(""" + INSERT INTO batch_exec(id, name) + VALUES (@x, @y); + """, CommandType.Text, handler: CustomHandler.Instance).Execute(items); + + Assert.Equal(100, count); + + var actual = _fixture.NpgsqlConnection.QuerySingle(""" + select count(1) from batch_exec + """); + Assert.Equal(100, actual); + } + + private class CustomHandler : CommandFactory<(int x, string y)> + { + public static readonly CustomHandler Instance = new(); + private CustomHandler() { } + + public override void AddParameters(in UnifiedCommand command, (int x, string y) args) + { + var ps = command.Parameters; + var p = command.CreateParameter(); + p.DbType = DbType.Int32; + p.Direction = ParameterDirection.Input; + p.Value = AsValue(args.x); + p.ParameterName = "x"; + ps.Add(p); + + p = command.CreateParameter(); + p.DbType = DbType.AnsiString; + p.Size = 40; + p.Direction = ParameterDirection.Input; + p.Value = AsValue(args.y); + p.ParameterName = "y"; + ps.Add(p); + } + + public override void UpdateParameters(in UnifiedCommand command, (int x, string y) args) + { + var ps = command.Parameters; + ps[0].Value = AsValue(args.x); + ps[1].Value = AsValue(args.y); + } + + public override bool CanPrepare => true; + } +} diff --git a/test/Dapper.AOT.Test/Integration/PostgresqlFixture.cs b/test/Dapper.AOT.Test/Integration/PostgresqlFixture.cs new file mode 100644 index 00000000..59329192 --- /dev/null +++ b/test/Dapper.AOT.Test/Integration/PostgresqlFixture.cs @@ -0,0 +1,52 @@ +using Npgsql; +using System.Threading.Tasks; +using Testcontainers.PostgreSql; +using Xunit; + +namespace Dapper.AOT.Test.Integration; + +[CollectionDefinition(Collection)] +public class SharedPostgresqlClient : ICollectionFixture +{ + public const string Collection = nameof(SharedPostgresqlClient); +} + +public sealed class PostgresqlFixture : IAsyncLifetime +{ + private readonly PostgreSqlContainer _postgresContainer = new PostgreSqlBuilder() + .WithImage("postgres:15-alpine") + .Build(); + + public string ConnectionString { get; private set; } = null!; + + private NpgsqlConnection? _sharedConnection; + + public NpgsqlConnection NpgsqlConnection + => _sharedConnection ??= CreateOpenConnection(); + + public NpgsqlConnection CreateOpenConnection() + { + var conn = new NpgsqlConnection(ConnectionString); + conn.Open(); + return conn; + } + + async Task IAsyncLifetime.InitializeAsync() + { + await _postgresContainer.StartAsync(); + ConnectionString = _postgresContainer.GetConnectionString(); + } + + async Task IAsyncLifetime.DisposeAsync() + { + await using (_postgresContainer) + { + var tmp = _sharedConnection; + _sharedConnection = null; + if (tmp is not null) + { + await tmp.DisposeAsync(); + } + } + } +}