コード例 #1
0
 public IAsyncEnumerator <TestDecodingData> GetAsyncEnumerator(
     CancellationToken cancellationToken = new CancellationToken())
 {
     using (NoSynchronizationContextScope.Enter())
         return(StartReplicationInternal(
                    CancellationTokenSource.CreateLinkedTokenSource(_baseCancellationToken, cancellationToken).Token));
 }
コード例 #2
0
        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);
                }
            }
        }
コード例 #4
0
 public ulong SaveAll(NpgsqlConnection connection, IEnumerable <TEntity> entities)
 {
     using (NoSynchronizationContextScope.Enter())
     {
         return(DoSaveAllAsync(connection, entities, CancellationToken.None).GetAwaiter().GetResult());
     }
 }
コード例 #5
0
        /// <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));
            }
        }
コード例 #6
0
    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);
        }
    }
コード例 #7
0
    /// <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));
        }
    }
コード例 #8
0
 /// <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));
 }
コード例 #9
0
 /// <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));
 }
コード例 #10
0
 /// <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));
 }
コード例 #11
0
 /// <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));
 }
コード例 #12
0
        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);
            }
        }
コード例 #13
0
        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);
            }
        }
コード例 #14
0
        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));
            }
        }
コード例 #15
0
ファイル: Startup.cs プロジェクト: fernandreu/recipe-manager
        // 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();
            });
        }
コード例 #16
0
        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));
コード例 #17
0
    /// <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)}.")
            });
コード例 #18
0
        /// <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));
        }
コード例 #19
0
        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);
                        }
                    }
                }
            }
        }
コード例 #20
0
 /// <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));
 }
コード例 #21
0
 /// <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));
 }
コード例 #22
0
 /// <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));
 }
コード例 #23
0
 /// <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));
 }
コード例 #24
0
 /// <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));
 }
コード例 #25
0
 /// <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));
 }
コード例 #26
0
 /// <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));
 }
コード例 #27
0
 /// <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));
 }
コード例 #28
0
 /// <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());
 }
コード例 #29
0
        public override ValueTask DisposeAsync()
#endif
        {
            using (NoSynchronizationContextScope.Enter())
                return(DisposeAsync(disposing: true, async: true));
        }