Beispiel #1
0
        private async Task <TResult> QueryFactoryAsync <TResult>(Func <CancellationToken, Task <TResult> > query, bool supportCache, CancellationToken cancellationToken = default)
        {
            if (query == null)
            {
                throw new ArgumentNullException(nameof(query));
            }

            AssertDisposed();

            var watch = Stopwatch.StartNew();

            try
            {
                var cacheKey = CacheKey <TResult>(supportCache);
                if (GetCache(cacheKey) is TResult results)
                {
                    return(results);
                }

                await _dataSession.EnsureConnectionAsync(cancellationToken).ConfigureAwait(false);

                results = await query(cancellationToken).ConfigureAwait(false);

                TriggerCallbacks();

                SetCache(cacheKey, results);

                return(results);
            }
            catch (Exception ex)
            {
                watch.Stop();
                LogCommand(watch.Elapsed, ex);

                throw;
            }
            finally
            {
                // if catch block didn't already log
                if (watch.IsRunning)
                {
                    watch.Stop();
                    LogCommand(watch.Elapsed);
                }

                _dataSession.ReleaseConnection();
                Dispose();
            }
        }
        /// <summary>
        /// Executes the command against the connection and converts the results to <typeparamref name="TEntity" /> objects asynchronously.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="factory">The <see langword="delegate" /> factory to convert the <see cref="T:System.Data.IDataReader" /> to <typeparamref name="TEntity" />.</param>
        /// <param name="cancellationToken">The cancellation instruction.</param>
        /// <returns>
        /// An <see cref="T:System.Collections.Generic.IEnumerable`1" /> of <typeparamref name="TEntity" /> objects.
        /// </returns>
        /// <exception cref="System.ArgumentNullException"><paramref name="factory"/> is null</exception>
        public async Task <IEnumerable <TEntity> > QueryAsync <TEntity>(Func <IDataReader, TEntity> factory, CancellationToken cancellationToken = default(CancellationToken))
            where TEntity : class
        {
            if (factory == null)
            {
                throw new ArgumentNullException(nameof(factory));
            }

            AssertDisposed();

            try
            {
                string cacheKey = CacheKey <TEntity>();
                if (GetCache(cacheKey) is List <TEntity> results)
                {
                    return(results);
                }

                results = new List <TEntity>();
                await _dataSession.EnsureConnectionAsync(cancellationToken).ConfigureAwait(false);

                LogCommand();
                using (var reader = await _command.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false))
                {
                    while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                    {
                        var entity = factory(reader);
                        results.Add(entity);
                    }
                }

                TriggerCallbacks();

                SetCache(cacheKey, results);
                return(results);
            }
            finally
            {
                _dataSession.ReleaseConnection();
                Dispose();
            }
        }
Beispiel #3
0
        private async Task MergeAsync(DataTable tableData, CancellationToken cancellationToken, Func <DbCommand, CancellationToken, Task> executeFactory)
        {
            var isBulk = _mergeDefinition.Mode == DataMergeMode.BulkCopy ||
                         (_mergeDefinition.Mode == DataMergeMode.Auto && tableData.Rows.Count > 1000);

            // Step 1, validate definition
            if (!Validate(_mergeDefinition, isBulk))
            {
                return;
            }

            try
            {
                await _dataSession
                .EnsureConnectionAsync(cancellationToken)
                .ConfigureAwait(false);

                var sqlConnection = _dataSession.Connection as SqlConnection;
                if (sqlConnection == null)
                {
                    throw new InvalidOperationException(
                              "Bulk-Copy only supported by SQL Server.  Make sure DataSession was create with a valid SqlConnection.");
                }

                var    sqlTransaction = _dataSession.Transaction as SqlTransaction;
                string mergeSql;

                if (isBulk)
                {
                    // Step 2, create temp table
                    string tableSql = DataMergeGenerator.BuildTable(_mergeDefinition);
                    using (var tableCommand = _dataSession.Connection.CreateCommand())
                    {
                        tableCommand.CommandText = tableSql;
                        tableCommand.CommandType = CommandType.Text;
                        tableCommand.Transaction = sqlTransaction;

                        await tableCommand
                        .ExecuteNonQueryAsync(cancellationToken)
                        .ConfigureAwait(false);
                    }

                    // Step 3, bulk copy into temp table
                    using (var bulkCopy = new SqlBulkCopy(sqlConnection, SqlBulkCopyOptions.Default, sqlTransaction))
                    {
                        bulkCopy.DestinationTableName = _mergeDefinition.TemporaryTable;
                        bulkCopy.BatchSize            = 1000;
                        foreach (var mergeColumn in _mergeDefinition.Columns.Where(c => !c.IsIgnored && c.CanBulkCopy))
                        {
                            bulkCopy.ColumnMappings.Add(mergeColumn.SourceColumn, mergeColumn.SourceColumn);
                        }

                        await bulkCopy
                        .WriteToServerAsync(tableData, cancellationToken)
                        .ConfigureAwait(false);
                    }

                    // Step 4, merge sql
                    mergeSql = DataMergeGenerator.BuildMerge(_mergeDefinition);
                }
                else
                {
                    // build merge from data
                    mergeSql = DataMergeGenerator.BuildMerge(_mergeDefinition, tableData);
                }

                // run merge statement
                using (var mergeCommand = _dataSession.Connection.CreateCommand())
                {
                    mergeCommand.CommandText = mergeSql;
                    mergeCommand.CommandType = CommandType.Text;
                    mergeCommand.Transaction = sqlTransaction;

                    // run merge with factory
                    await executeFactory(mergeCommand, cancellationToken)
                    .ConfigureAwait(false);
                }
            }
            finally
            {
                _dataSession.ReleaseConnection();
            }
        }