public IAsyncEnumerator <TestDecodingData> GetAsyncEnumerator( CancellationToken cancellationToken = new CancellationToken()) { using (NoSynchronizationContextScope.Enter()) return(StartReplicationInternal( CancellationTokenSource.CreateLinkedTokenSource(_baseCancellationToken, cancellationToken).Token)); }
public override Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { ValidateArguments(buffer, offset, count); using (NoSynchronizationContextScope.Enter()) return(ReadAsync(new Memory <byte>(buffer, offset, count), cancellationToken).AsTask()); }
/// <summary> /// Instructs the server to start streaming the WAL for physical replication, starting at WAL location /// <paramref name="walLocation"/>. The server can reply with an error, for example if the requested /// section of the WAL has already been recycled. /// </summary> /// <remarks> /// If the client requests a timeline that's not the latest but is part of the history of the server, the server /// will stream all the WAL on that timeline starting from the requested start point up to the point where the /// server switched to another timeline. /// </remarks> /// <param name="slot"> /// The replication slot that will be updated as replication progresses so that the server /// knows which WAL segments are still needed by the standby. /// </param> /// <param name="walLocation">The WAL location to begin streaming at.</param> /// <param name="cancellationToken">The token to be used for stopping the replication.</param> /// <param name="timeline">Streaming starts on timeline tli.</param> /// <returns>A <see cref="Task{T}"/> representing an <see cref="IAsyncEnumerable{NpgsqlXLogDataMessage}"/> that /// can be used to stream WAL entries in form of <see cref="XLogDataMessage"/> instances.</returns> public IAsyncEnumerable <XLogDataMessage> StartReplication(PhysicalReplicationSlot?slot, NpgsqlLogSequenceNumber walLocation, CancellationToken cancellationToken, uint timeline = default) { using (NoSynchronizationContextScope.Enter()) return(StartPhysicalReplication(slot, walLocation, cancellationToken, timeline)); async IAsyncEnumerable <XLogDataMessage> StartPhysicalReplication(PhysicalReplicationSlot?slot, NpgsqlLogSequenceNumber walLocation, [EnumeratorCancellation] CancellationToken cancellationToken, uint timeline) { var builder = new StringBuilder("START_REPLICATION"); if (slot != null) { builder.Append(" SLOT ").Append(slot.Name); } builder.Append(" PHYSICAL ").Append(walLocation); if (timeline != default) { builder.Append(" TIMELINE ").Append(timeline.ToString(CultureInfo.InvariantCulture)); } var enumerator = StartReplicationInternalWrapper(builder.ToString(), bypassingStream: false, cancellationToken); while (await enumerator.MoveNextAsync()) { yield return(enumerator.Current); } } }
public ulong SaveAll(NpgsqlConnection connection, IEnumerable <TEntity> entities) { using (NoSynchronizationContextScope.Enter()) { return(DoSaveAllAsync(connection, entities, CancellationToken.None).GetAwaiter().GetResult()); } }
/// <summary> /// Creates a <see cref="PhysicalReplicationSlot"/> that wraps a PostgreSQL physical replication slot and /// can be used to start physical streaming replication /// </summary> /// <param name="slotName"> /// The name of the slot to create. Must be a valid replication slot name /// (see <a href="https://www.postgresql.org/docs/current/warm-standby.html#STREAMING-REPLICATION-SLOTS-MANIPULATION">Section 26.2.6.1</a>). /// </param> /// <param name="isTemporary"> /// <see langword="true"/> if this replication slot shall be a temporary one; otherwise /// <see langword="false"/>. Temporary slots are not saved to disk and are automatically dropped on error or /// when the session has finished. /// </param> /// <param name="reserveWal"> /// If this is set to <see langword="true"/> this physical replication slot reserves WAL immediately. Otherwise, /// WAL is only reserved upon connection from a streaming replication client. /// </param> /// <param name="cancellationToken"> /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None"/>. /// </param> /// <returns>A <see cref="PhysicalReplicationSlot"/> that wraps the newly-created replication slot. /// </returns> public Task <PhysicalReplicationSlot> CreateReplicationSlot( string slotName, bool isTemporary = false, bool reserveWal = false, CancellationToken cancellationToken = default) { using var _ = NoSynchronizationContextScope.Enter(); return(CreatePhysicalReplicationSlot()); async Task <PhysicalReplicationSlot> CreatePhysicalReplicationSlot() { var builder = new StringBuilder("CREATE_REPLICATION_SLOT ").Append(slotName); if (isTemporary) { builder.Append(" TEMPORARY"); } builder.Append(" PHYSICAL"); if (reserveWal) { builder.Append(" RESERVE_WAL"); } var slotOptions = await CreateReplicationSlot(builder.ToString(), isTemporary, cancellationToken); return(new PhysicalReplicationSlot(slotOptions.SlotName)); } }
private static void SetupSchema(IDocumentStore documentStore, MartenConfig martenConfig, int retryLeft = 1) { try { if (martenConfig.ShouldRecreateDatabase) { documentStore.Advanced.Clean.CompletelyRemoveAll(); } using (NoSynchronizationContextScope.Enter()) { documentStore.Schema.ApplyAllConfiguredChangesToDatabaseAsync().Wait(); } } catch (Exception ex) { Console.WriteLine(ex); if (retryLeft == 0) { throw; } Thread.Sleep(1000); SetupSchema(documentStore, martenConfig, --retryLeft); } }
/// <summary> /// Creates a <see cref="PhysicalReplicationSlot"/> that wraps a PostgreSQL physical replication slot and /// can be used to start physical streaming replication /// </summary> /// <param name="slotName"> /// The name of the slot to create. Must be a valid replication slot name /// (see <a href="https://www.postgresql.org/docs/current/warm-standby.html#STREAMING-REPLICATION-SLOTS-MANIPULATION">Section 26.2.6.1</a>). /// </param> /// <param name="isTemporary"> /// <see langword="true"/> if this replication slot shall be a temporary one; otherwise /// <see langword="false"/>. Temporary slots are not saved to disk and are automatically dropped on error or /// when the session has finished. /// </param> /// <param name="reserveWal"> /// If this is set to <see langword="true"/> this physical replication slot reserves WAL immediately. Otherwise, /// WAL is only reserved upon connection from a streaming replication client. /// </param> /// <param name="cancellationToken"> /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None"/>. /// </param> /// <returns>A <see cref="Task{T}"/> representing a <see cref="PhysicalReplicationSlot"/> that represents the /// newly-created replication slot. /// </returns> public Task <PhysicalReplicationSlot> CreateReplicationSlot( string slotName, bool isTemporary = false, bool reserveWal = false, CancellationToken cancellationToken = default) { CheckDisposed(); using var _ = NoSynchronizationContextScope.Enter(); return(CreatePhysicalReplicationSlot(slotName, isTemporary, reserveWal, cancellationToken)); async Task <PhysicalReplicationSlot> CreatePhysicalReplicationSlot(string slotName, bool isTemporary, bool reserveWal, CancellationToken cancellationToken) { var builder = new StringBuilder("CREATE_REPLICATION_SLOT ").Append(slotName); if (isTemporary) { builder.Append(" TEMPORARY"); } builder.Append(" PHYSICAL"); if (reserveWal) { builder.Append(" RESERVE_WAL"); } var command = builder.ToString(); LogMessages.CreatingReplicationSlot(Logger, slotName, command, Connector.Id); var slotOptions = await CreateReplicationSlot(builder.ToString(), cancellationToken); return(new PhysicalReplicationSlot(slotOptions.SlotName)); } }
/// <summary> /// <para> /// Async terminates the ongoing binary import and puts the connection back into the idle state, where regular commands can be executed. /// </para> /// <para> /// Note that if <see cref="CompleteAsync" /> hasn't been invoked before calling this, the import will be cancelled and all changes will /// be reverted. /// </para> /// </summary> public ValueTask CloseAsync(CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { return(new ValueTask(Task.FromCanceled(cancellationToken))); } using (NoSynchronizationContextScope.Enter()) return(CloseAsync(true, cancellationToken)); }
/// <summary> /// Writes an entire row of columns. /// Equivalent to calling <see cref="StartRow()"/>, followed by multiple <see cref="Write{T}(T)"/> /// on each value. /// </summary> /// <param name="cancellationToken"> /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None"/>. /// </param> /// <param name="values">An array of column values to be written as a single row</param> public Task WriteRowAsync(CancellationToken cancellationToken = default, params object[] values) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled(cancellationToken)); } using (NoSynchronizationContextScope.Enter()) return(WriteRow(true, cancellationToken, values)); }
/// <summary> /// Writes a single null column value. /// </summary> public Task WriteNullAsync(CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled(cancellationToken)); } using (NoSynchronizationContextScope.Enter()) return(WriteNull(true, cancellationToken)); }
/// <summary> /// Writes a single column in the current row as type <paramref name="dataTypeName"/>. /// </summary> /// <param name="value">The value to be written</param> /// <param name="dataTypeName"> /// In some cases <typeparamref name="T"/> isn't enough to infer the data type to be written to /// the database. This parameter and be used to unambiguously specify the type. /// </param> /// <param name="cancellationToken"> /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None"/>. /// </param> /// <typeparam name="T">The .NET type of the column to be written.</typeparam> public Task WriteAsync <T>([AllowNull] T value, string dataTypeName, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled(cancellationToken)); } using (NoSynchronizationContextScope.Enter()) return(Write(value, dataTypeName, true, cancellationToken)); }
public ValueTask <bool> MoveNextAsync() { if (_tupleEnumerable.State != RowState.Reading) { throw new ObjectDisposedException(null); } using (NoSynchronizationContextScope.Enter()) return(MoveNextCore()); async ValueTask <bool> MoveNextCore() { // Consume the previous column if (_pos != -1) { await _value.Consume(_cancellationToken); } if (_pos + 1 == _numColumns) { return(false); } _pos++; // Read the next column await _readBuffer.Ensure(1, async : true); var kind = (TupleDataKind)_readBuffer.ReadByte(); int len; switch (kind) { case TupleDataKind.Null: case TupleDataKind.UnchangedToastedValue: len = 0; break; case TupleDataKind.TextValue: case TupleDataKind.BinaryValue: if (_readBuffer.ReadBytesLeft < 4) { using var tokenRegistration = _readBuffer.Connector.StartNestedCancellableOperation(_cancellationToken); await _readBuffer.Ensure(4, async : true); } len = _readBuffer.ReadInt32(); break; default: throw new ArgumentOutOfRangeException(); } _value.Reset(kind, len, _rowDescription[_pos]); return(true); } }
public override async Task <int> ReadAsync([NotNull] byte[] buffer, int offset, int count, CancellationToken token) { using (NoSynchronizationContextScope.Enter()) { CheckDisposed(); count = Math.Min(count, _row.ColumnLen - _row.PosInColumn); var read = await _row.Buffer.ReadAllBytes(buffer, offset, count, true, true); _row.PosInColumn += read; return(read); } }
public ValueTask <ulong> SaveAllAsync(NpgsqlConnection connection, IEnumerable <TEntity> entities, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { return(new ValueTask <ulong>(Task.FromCanceled <ulong>(cancellationToken))); } using (NoSynchronizationContextScope.Enter()) { return(DoSaveAllAsync(connection, entities)); } }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, AppDbContext context, IOptionsMonitor <DbOptions> options, IUserService userService) { if (options.CurrentValue.Delete) { context.Database.EnsureDeleted(); } if (options.CurrentValue.Create) { context.Database.EnsureCreated(); } if (options.CurrentValue.Migrate) { context.Database.Migrate(); } // Without the using statement, Azure Pipelines might get a deadlock using (NoSynchronizationContextScope.Enter()) { // TODO: This system can be used to set an admin password in production too (as long as that is managed securely) userService.SetPasswordAsync(FakeDataSeeder.FakeAdminName, "Abcd123#").Wait(); } CurrentEnvironment = env; if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } //app.UseHttpsRedirection(); app.UseCors("AllowMyApp"); app.UseStatusCodePagesWithReExecute("/error/{0}"); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
public override ValueTask <int> ReadAsync(Memory <byte> buffer, CancellationToken cancellationToken = default) #endif { CheckDisposed(); var count = Math.Min(buffer.Length, _len - _read); if (count == 0) { return(new ValueTask <int>(0)); } using (NoSynchronizationContextScope.Enter()) return(ReadLong(this, buffer.Slice(0, count), cancellationToken));
/// <summary> /// This API is for internal use and for implementing logical replication plugins. /// It is not meant to be consumed in common Npgsql usage scenarios. /// </summary> /// <remarks> /// Creates a new replication slot and returns information about the newly-created slot. /// </remarks> /// <param name="connection">The <see cref="LogicalReplicationConnection"/> to use for creating the /// replication slot</param> /// <param name="slotName">The name of the slot to create. Must be a valid replication slot name (see /// <a href="https://www.postgresql.org/docs/current/warm-standby.html#STREAMING-REPLICATION-SLOTS-MANIPULATION"> /// https://www.postgresql.org/docs/current/warm-standby.html#STREAMING-REPLICATION-SLOTS-MANIPULATION</a>). /// </param> /// <param name="outputPlugin">The name of the output plugin used for logical decoding (see /// <a href="https://www.postgresql.org/docs/current/logicaldecoding-output-plugin.html"> /// https://www.postgresql.org/docs/current/logicaldecoding-output-plugin.html</a>). /// </param> /// <param name="isTemporary"><see langword="true"/> if this replication slot shall be temporary one; otherwise /// <see langword="false"/>. Temporary slots are not saved to disk and are automatically dropped on error or /// when the session has finished.</param> /// <param name="slotSnapshotInitMode">A <see cref="LogicalSlotSnapshotInitMode"/> to specify what to do with the /// snapshot created during logical slot initialization. <see cref="LogicalSlotSnapshotInitMode.Export"/>, which is /// also the default, will export the snapshot for use in other sessions. This option can't be used inside a /// transaction. <see cref="LogicalSlotSnapshotInitMode.Use"/> will use the snapshot for the current transaction /// executing the command. This option must be used in a transaction, and <see cref="LogicalSlotSnapshotInitMode.Use"/> /// must be the first command run in that transaction. Finally, <see cref="LogicalSlotSnapshotInitMode.NoExport"/> will /// just use the snapshot for logical decoding as normal but won't do anything else with it.</param> /// <param name="twoPhase"> /// If <see langword="true"/>, this logical replication slot supports decoding of two-phase transactions. With this option, /// two-phase commands like PREPARE TRANSACTION, COMMIT PREPARED and ROLLBACK PREPARED are decoded and transmitted. /// The transaction will be decoded and transmitted at PREPARE TRANSACTION time. The default is <see langword="false"/>. /// </param> /// <param name="cancellationToken"> /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None"/>. /// </param> /// <returns>A <see cref="Task{T}"/> representing a <see cref="ReplicationSlotOptions"/> class that /// can be used to initialize instances of <see cref="ReplicationSlot"/> subclasses.</returns> public static Task <ReplicationSlotOptions> CreateLogicalReplicationSlot( this LogicalReplicationConnection connection, string slotName, string outputPlugin, bool isTemporary = false, LogicalSlotSnapshotInitMode?slotSnapshotInitMode = null, bool twoPhase = false, CancellationToken cancellationToken = default) { connection.CheckDisposed(); using var _ = NoSynchronizationContextScope.Enter(); return(CreateLogicalReplicationSlotCore()); Task <ReplicationSlotOptions> CreateLogicalReplicationSlotCore() { if (slotName is null) { throw new ArgumentNullException(nameof(slotName)); } if (outputPlugin is null) { throw new ArgumentNullException(nameof(outputPlugin)); } cancellationToken.ThrowIfCancellationRequested(); var builder = new StringBuilder("CREATE_REPLICATION_SLOT ").Append(slotName); if (isTemporary) { builder.Append(" TEMPORARY"); } builder.Append(" LOGICAL ").Append(outputPlugin); builder.Append(slotSnapshotInitMode switch { // EXPORT_SNAPSHOT is the default since it has been introduced. // We don't set it unless it is explicitly requested so that older backends can digest the query too. null => string.Empty, LogicalSlotSnapshotInitMode.Export => " EXPORT_SNAPSHOT", LogicalSlotSnapshotInitMode.Use => " USE_SNAPSHOT", LogicalSlotSnapshotInitMode.NoExport => " NOEXPORT_SNAPSHOT", _ => throw new ArgumentOutOfRangeException(nameof(slotSnapshotInitMode), slotSnapshotInitMode, $"Unexpected value {slotSnapshotInitMode} for argument {nameof(slotSnapshotInitMode)}.") });
/// <summary> /// Instructs the server to start streaming the WAL for physical replication, starting at WAL location /// <paramref name="walLocation"/>. The server can reply with an error, for example if the requested /// section of the WAL has already been recycled. /// </summary> /// <remarks> /// If the client requests a timeline that's not the latest but is part of the history of the server, the server /// will stream all the WAL on that timeline starting from the requested start point up to the point where the /// server switched to another timeline. /// </remarks> /// <param name="slot"> /// The replication slot that will be updated as replication progresses so that the server /// knows which WAL segments are still needed by the standby. /// </param> /// <param name="walLocation">The WAL location to begin streaming at.</param> /// <param name="cancellationToken">The token to be used for stopping the replication.</param> /// <param name="timeline">Streaming starts on timeline tli.</param> /// <returns>A <see cref="Task{T}"/> representing an <see cref="IAsyncEnumerable{NpgsqlXLogDataMessage}"/> that /// can be used to stream WAL entries in form of <see cref="XLogDataMessage"/> instances.</returns> public IAsyncEnumerable <XLogDataMessage> StartReplication(PhysicalReplicationSlot?slot, NpgsqlLogSequenceNumber walLocation, CancellationToken cancellationToken, uint timeline = default) { using var _ = NoSynchronizationContextScope.Enter(); var builder = new StringBuilder("START_REPLICATION"); if (slot != null) { builder.Append(" SLOT ").Append(slot.Name); } builder.Append(" PHYSICAL ").Append(walLocation); if (timeline != default) { builder.Append(" TIMELINE ").Append(timeline.ToString(CultureInfo.InvariantCulture)); } return(StartReplicationInternal(builder.ToString(), bypassingStream: false, cancellationToken)); }
private void applyProjections(IDocumentSession session, ICollection <EventProjection> projections, IEnumerable <TView> views) { var idAssigner = session.Tenant.IdAssignmentFor <TView>(); var resolver = session.Tenant.StorageFor <TView>(); var viewMap = views.ToDictionary(view => (TId)resolver.IdentityFor(view), view => view); foreach (var eventProjection in projections) { var viewId = eventProjection.ViewId; var hasExistingView = viewMap.TryGetValue(viewId, out var view); if (!hasExistingView) { if (eventProjection.Type == ProjectionEventType.CreateAndUpdate) { view = newView(session.Tenant, idAssigner, viewId); viewMap.Add(viewId, view); hasExistingView = true; } } using (NoSynchronizationContextScope.Enter()) { if (eventProjection.Type == ProjectionEventType.CreateAndUpdate || (eventProjection.Type == ProjectionEventType.UpdateOnly && hasExistingView)) { session.Store(view); eventProjection.ProjectTo(session, view).Wait(); } else if (eventProjection.Type == ProjectionEventType.Delete && hasExistingView) { var shouldDeleteTask = eventProjection.ShouldDelete(session, view); shouldDeleteTask.Wait(); if (shouldDeleteTask.Result) { session.Delete(view); } } } } }
/// <summary> /// Read some information associated to a replication slot. /// <remarks> /// This command is currently only supported for physical replication slots. /// </remarks> /// </summary> /// <param name="slotName"> /// The name of the slot to read. Must be a valid replication slot name /// </param> /// <param name="cancellationToken"> /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None"/>. /// </param> /// <returns>A <see cref="Task{T}"/> representing a <see cref="PhysicalReplicationSlot"/> or <see langword="null"/> /// if the replication slot does not exist.</returns> public Task <PhysicalReplicationSlot?> ReadReplicationSlot(string slotName, CancellationToken cancellationToken = default) { using (NoSynchronizationContextScope.Enter()) return(ReadReplicationSlotInternal(slotName, cancellationToken)); }
/// <summary> /// Starts reading a single row, must be invoked before reading any columns. /// </summary> /// <returns> /// The number of columns in the row. -1 if there are no further rows. /// Note: This will currently be the same value for all rows, but this may change in the future. /// </returns> public ValueTask <int> StartRowAsync(CancellationToken cancellationToken = default) { using (NoSynchronizationContextScope.Enter()) return(StartRow(true, cancellationToken)); }
/// <summary> /// Reads the current column, returns its value according to <paramref name="type"/> and /// moves ahead to the next column. /// If the column is null an exception is thrown. /// </summary> /// <param name="type"> /// In some cases <typeparamref name="T"/> isn't enough to infer the data type coming in from the /// database. This parameter can be used to unambiguously specify the type. An example is the JSONB /// type, for which <typeparamref name="T"/> will be a simple string but for which /// <paramref name="type"/> must be specified as <see cref="NpgsqlDbType.Jsonb"/>. /// </param> /// <param name="cancellationToken"> /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None"/>. /// </param> /// <typeparam name="T">The .NET type of the column to be read.</typeparam> /// <returns>The value of the column</returns> public ValueTask <T> ReadAsync <T>(NpgsqlDbType type, CancellationToken cancellationToken = default) { using (NoSynchronizationContextScope.Enter()) return(Read <T>(type, true, cancellationToken)); }
/// <summary> /// Opens a large object on the backend, returning a stream controlling this remote object. /// Note that this method, as well as operations on the stream must be wrapped inside a transaction. /// </summary> /// <param name="oid">Oid of the object</param> /// <param name="cancellationToken"> /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None"/>. /// </param> /// <returns>An NpgsqlLargeObjectStream</returns> public Task <NpgsqlLargeObjectStream> OpenReadWriteAsync(uint oid, CancellationToken cancellationToken = default) { using (NoSynchronizationContextScope.Enter()) return(OpenReadWrite(oid, true, cancellationToken)); }
/// <summary> /// Deletes a large object on the backend. /// </summary> /// <param name="oid">Oid of the object to delete</param> /// <param name="cancellationToken"> /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None"/>. /// </param> public Task UnlinkAsync(uint oid, CancellationToken cancellationToken = default) { using (NoSynchronizationContextScope.Enter()) return(ExecuteFunction <object>("lo_unlink", true, cancellationToken, (int)oid)); }
/// <summary> /// Imports a large object to be stored as a large object in the database from a file stored on the backend. This requires superuser permissions. /// </summary> /// <param name="path">Path to read the file on the backend</param> /// <param name="oid">A preferred oid, or specify 0 if one should be automatically assigned</param> /// <param name="cancellationToken"> /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None"/>. /// </param> public Task ImportRemoteAsync(string path, uint oid, CancellationToken cancellationToken = default) { using (NoSynchronizationContextScope.Enter()) return(ExecuteFunction <object>("lo_import", true, cancellationToken, path, (int)oid)); }
/// <summary> /// <para> /// Async terminates the ongoing binary import and puts the connection back into the idle state, where regular commands can be executed. /// </para> /// <para> /// Note that if <see cref="CompleteAsync" /> hasn't been invoked before calling this, the import will be cancelled and all changes will /// be reverted. /// </para> /// </summary> public ValueTask DisposeAsync() { using (NoSynchronizationContextScope.Enter()) return(CloseAsync(true)); }
/// <summary> /// Reads <i>count</i> bytes from the large object. The only case when fewer bytes are read is when end of stream is reached. /// </summary> /// <param name="buffer">The buffer where read data should be stored.</param> /// <param name="offset">The offset in the buffer where the first byte should be read.</param> /// <param name="count">The maximum number of bytes that should be read.</param> /// <param name="cancellationToken"> /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None"/>. /// </param> /// <returns>How many bytes actually read, or 0 if end of file was already reached.</returns> public override Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { using (NoSynchronizationContextScope.Enter()) return(Read(buffer, offset, count, true, cancellationToken)); }
/// <summary> /// Cancels and terminates an ongoing import. Any data already written will be discarded. /// </summary> public Task CancelAsync() { using (NoSynchronizationContextScope.Enter()) return(((NpgsqlRawCopyStream)BaseStream).CancelAsync()); }
public override ValueTask DisposeAsync() #endif { using (NoSynchronizationContextScope.Enter()) return(DisposeAsync(disposing: true, async: true)); }