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();
+ }
+ }
+ }
+}