/
NpgsqlBatch.cs
203 lines (170 loc) · 7.1 KB
/
NpgsqlBatch.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
using System;
using System.Data;
using System.Data.Common;
using System.Threading;
using System.Threading.Tasks;
using Npgsql.Internal;
namespace Npgsql;
/// <inheritdoc />
public class NpgsqlBatch : DbBatch
{
internal const int DefaultBatchCommandsSize = 5;
private protected NpgsqlCommand Command { get; }
/// <inheritdoc />
protected override DbBatchCommandCollection DbBatchCommands => BatchCommands;
/// <inheritdoc cref="DbBatch.BatchCommands"/>
public new NpgsqlBatchCommandCollection BatchCommands { get; }
/// <inheritdoc />
public override int Timeout
{
get => Command.CommandTimeout;
set => Command.CommandTimeout = value;
}
/// <inheritdoc cref="DbBatch.Connection"/>
public new NpgsqlConnection? Connection
{
get => Command.Connection;
set => Command.Connection = value;
}
/// <inheritdoc />
protected override DbConnection? DbConnection
{
get => Connection;
set => Connection = (NpgsqlConnection?)value;
}
/// <inheritdoc cref="DbBatch.Transaction"/>
public new NpgsqlTransaction? Transaction
{
get => Command.Transaction;
set => Command.Transaction = value;
}
/// <inheritdoc />
protected override DbTransaction? DbTransaction
{
get => Transaction;
set => Transaction = (NpgsqlTransaction?)value;
}
/// <summary>
/// Controls whether to place error barriers between all batch commands within this batch. Default to <see langword="false" />.
/// </summary>
/// <remarks>
/// <para>
/// By default, any exception in a command causes later commands in the batch to be skipped, and earlier commands to be rolled back.
/// Enabling error barriers ensures that errors do not affect other commands in the batch.
/// </para>
/// <para>
/// Note that if the batch is executed within an explicit transaction, the first error places the transaction in a failed state,
/// causing all later commands to fail in any case. As a result, this option is useful mainly when there is no explicit transaction.
/// </para>
/// <para>
/// At the PostgreSQL wire protocol level, this corresponds to inserting a Sync message between each command, rather than grouping
/// all the batch's commands behind a single terminating Sync.
/// </para>
/// <para>
/// To control error barriers on a command-by-command basis, see <see cref="NpgsqlBatchCommand.AppendErrorBarrier" />.
/// </para>
/// </remarks>
public bool EnableErrorBarriers
{
get => Command.EnableErrorBarriers;
set => Command.EnableErrorBarriers = value;
}
/// <summary>
/// Marks all of the batch's result columns as either known or unknown.
/// Unknown results column are requested them from PostgreSQL in text format, and Npgsql makes no
/// attempt to parse them. They will be accessible as strings only.
/// </summary>
internal bool AllResultTypesAreUnknown
{
get => Command.AllResultTypesAreUnknown;
set => Command.AllResultTypesAreUnknown = value;
}
/// <summary>
/// Initializes a new <see cref="NpgsqlBatch"/>.
/// </summary>
/// <param name="connection">A <see cref="NpgsqlConnection"/> that represents the connection to a PostgreSQL server.</param>
/// <param name="transaction">The <see cref="NpgsqlTransaction"/> in which the <see cref="NpgsqlCommand"/> executes.</param>
public NpgsqlBatch(NpgsqlConnection? connection = null, NpgsqlTransaction? transaction = null)
{
GC.SuppressFinalize(this);
Command = new(DefaultBatchCommandsSize);
BatchCommands = new NpgsqlBatchCommandCollection(Command.InternalBatchCommands);
Connection = connection;
Transaction = transaction;
}
internal NpgsqlBatch(NpgsqlConnector connector)
{
GC.SuppressFinalize(this);
Command = new(connector, DefaultBatchCommandsSize);
BatchCommands = new NpgsqlBatchCommandCollection(Command.InternalBatchCommands);
}
private protected NpgsqlBatch(NpgsqlDataSourceCommand command)
{
GC.SuppressFinalize(this);
Command = command;
BatchCommands = new NpgsqlBatchCommandCollection(Command.InternalBatchCommands);
}
/// <inheritdoc />
protected override DbBatchCommand CreateDbBatchCommand() => CreateBatchCommand();
/// <inheritdoc cref="DbBatch.CreateBatchCommand"/>
public new NpgsqlBatchCommand CreateBatchCommand()
=> new NpgsqlBatchCommand();
/// <inheritdoc />
protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
=> ExecuteReader(behavior);
/// <inheritdoc cref="DbBatch.ExecuteReader"/>
public new NpgsqlDataReader ExecuteReader(CommandBehavior behavior = CommandBehavior.Default)
=> Command.ExecuteReader(behavior);
/// <inheritdoc />
protected override async Task<DbDataReader> ExecuteDbDataReaderAsync(
CommandBehavior behavior,
CancellationToken cancellationToken)
=> await ExecuteReaderAsync(behavior, cancellationToken).ConfigureAwait(false);
/// <inheritdoc cref="DbBatch.ExecuteReaderAsync(CancellationToken)"/>
public new Task<NpgsqlDataReader> ExecuteReaderAsync(CancellationToken cancellationToken = default)
=> Command.ExecuteReaderAsync(cancellationToken);
/// <inheritdoc cref="DbBatch.ExecuteReaderAsync(CommandBehavior,CancellationToken)"/>
public new Task<NpgsqlDataReader> ExecuteReaderAsync(
CommandBehavior behavior,
CancellationToken cancellationToken = default)
=> Command.ExecuteReaderAsync(behavior, cancellationToken);
/// <inheritdoc />
public override int ExecuteNonQuery()
=> Command.ExecuteNonQuery();
/// <inheritdoc />
public override Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken = default)
=> Command.ExecuteNonQueryAsync(cancellationToken);
/// <inheritdoc />
public override object? ExecuteScalar()
=> Command.ExecuteScalar();
/// <inheritdoc />
public override Task<object?> ExecuteScalarAsync(CancellationToken cancellationToken = default)
=> Command.ExecuteScalarAsync(cancellationToken);
/// <inheritdoc />
public override void Prepare()
=> Command.Prepare();
/// <inheritdoc />
public override Task PrepareAsync(CancellationToken cancellationToken = default)
=> Command.PrepareAsync(cancellationToken);
/// <inheritdoc />
public override void Cancel() => Command.Cancel();
/// <inheritdoc />
public override void Dispose()
{
Command.ResetTransaction();
if (Command.IsCacheable && Connection is not null && Connection.CachedBatch is null)
{
BatchCommands.Clear();
Command.Reset();
Connection.CachedBatch = this;
return;
}
Command.IsCacheable = false;
}
internal static NpgsqlBatch CreateCachedBatch(NpgsqlConnection connection)
{
var batch = new NpgsqlBatch(connection);
batch.Command.IsCacheable = true;
return batch;
}
}