Exemple #1
0
        /// <summary>
        /// 指定されたレコードをバルク方式でテーブルに非同期的に挿入します。
        /// </summary>
        /// <typeparam name="T">テーブルにマッピングされた型</typeparam>
        /// <param name="data">挿入するデータ</param>
        /// <returns>影響した行数</returns>
        public override async Task <int> BulkInsertAsync <T>(IEnumerable <T> data)
        {
            //--- 挿入処理本体
            Func <IEnumerable <T>, IDbTransaction, Task <int> > insert = async(collection, transaction) =>
            {
                var result = 0;
                var sql    = PrimitiveSql.CreateInsert <T>(this.DbKind, false, true);
                foreach (var x in collection)
                {
                    var value = await this.Connection.ExecuteAsync(sql, x, transaction, this.Timeout).ConfigureAwait(false);

                    Interlocked.Add(ref result, value);
                }
                return(result);
            };

            //--- トランザクションが外部から指定されている場合はそれを利用
            if (this.Transaction != null)
            {
                return(await insert(data, this.Transaction).ConfigureAwait(false));
            }

            //--- トランザクションが外部から指定されていない場合は新規に作成
            //--- SQLiteにおけるバルクインサートの魔法
            using (var transaction = this.Connection.StartTransaction())
            {
                var result = await insert(data, transaction.Raw).ConfigureAwait(false);

                transaction.Complete();
                return(result);
            }
        }
        /// <summary>
        /// バルク方式で指定のデータを挿入するためのコマンドを生成します。
        /// </summary>
        /// <typeparam name="T">テーブルにマッピングされた型</typeparam>
        /// <param name="data">挿入するデータ</param>
        /// <returns>コマンド</returns>
        private DbCommand CreateBulkInsertCommand <T>(IEnumerable <T> data)
        {
            //--- 実体化
            data = data.Materialize();

            //--- build DbCommand
            var     factory = DbProvider.GetFactory(this.DbKind);
            dynamic command = factory.CreateCommand();

            command.Connection     = (dynamic)this.Connection;
            command.CommandText    = PrimitiveSql.CreateInsert <T>(this.DbKind, false, true);
            command.BindByName     = true;
            command.ArrayBindCount = data.Count();
            if (this.Timeout.HasValue)
            {
                command.CommandTimeout = this.Timeout.Value;
            }

            //--- bind params
            foreach (var x in TableMappingInfo.Create <T>().Columns)
            {
                var getter = AccessorCache <T> .LookupGet(x.PropertyName);

                dynamic parameter = factory.CreateParameter();
                parameter.ParameterName = x.PropertyName;
                parameter.DbType        = x.ColumnType;
                parameter.Value         = data.Select(y => getter(y)).ToArray();
                command.Parameters.Add(parameter);
            }
            return(command);
        }
Exemple #3
0
        /// <summary>
        /// 指定されたレコードをテーブルに非同期的に挿入します。
        /// </summary>
        /// <typeparam name="T">テーブルにマッピングされた型</typeparam>
        /// <param name="data">挿入するデータ</param>
        /// <param name="useSequence">シーケンスを利用するかどうか</param>
        /// <param name="setIdentity">自動採番のID列に値を設定するかどうか</param>
        /// <returns>影響した行数</returns>
        public virtual Task <int> InsertAsync <T>(T data, bool useSequence, bool setIdentity)
        {
            var type = TypeHelper.GetElementType <T>() ?? typeof(T);
            var sql  = PrimitiveSql.CreateInsert(this.DbKind, type, useSequence, setIdentity);

            return(this.Connection.ExecuteAsync(sql, data, this.Transaction, this.Timeout));
        }
        /// <summary>
        /// レコードを挿入し、そのレコードに自動採番されたIDを取得するSQLを生成します。
        /// </summary>
        /// <typeparam name="T">テーブルにマッピングされた型</typeparam>
        /// <returns>SQL文</returns>
        protected override string CreateInsertAndGetSql <T>()
        {
            var sequence = TableMappingInfo.Create <T>().Columns.First(x => x.IsPrimaryKey).Sequence;

            return
                ($@"{PrimitiveSql.CreateInsert<T>(this.DbKind)};
select currval({sequence.FullName}) as Id;");
        }
        public void シーケンスを利用するInsert文生成()
        {
            var actual1 = PrimitiveSql.CreateInsert(DbKind.SqlServer, typeof(Person));
            var actual2 = PrimitiveSql.CreateInsert <Person>(DbKind.SqlServer);
            var expect  =
                @"insert into dbo.Person
(
    名前,
    Age,
    HasChildren
)
values
(
    @Name,
    next value for dbo.AgeSeq,
    @HasChildren
)";

            actual1.Is(expect);
            actual2.Is(expect);
        }
        /// <summary>
        /// InsertAndGetするためのパラメーターを生成します。
        /// </summary>
        /// <typeparam name="T">テーブルにマッピングされた型</typeparam>
        /// <param name="data">挿入するデータ</param>
        /// <returns>パラメーター</returns>
        private Tuple <DbCommand, DbParameter> CreateInsertAndGetParameter <T>(T data)
        {
            //--- command
            var     factory = DbProvider.GetFactory(this.DbKind);
            dynamic command = factory.CreateCommand();

            command.BindByName = true;
            command.Connection = (dynamic)this.Connection;
            if (this.Timeout.HasValue)
            {
                command.CommandTimeout = this.Timeout.Value;
            }

            //--- parameters
            DbParameter output = null;

            foreach (var x in TableMappingInfo.Create <T>().Columns)
            {
                dynamic parameter = factory.CreateParameter();
                parameter.ParameterName = x.PropertyName;
                parameter.DbType        = x.ColumnType;
                if (x.IsPrimaryKey)
                {
                    parameter.Direction = ParameterDirection.Output;
                    output = parameter;
                    command.CommandText =
                        $@"{PrimitiveSql.CreateInsert<T>(this.DbKind)}
returning {x.ColumnName} into :{x.PropertyName}";
                }
                else
                {
                    parameter.Direction = ParameterDirection.Input;
                    parameter.Value     = AccessorCache <T> .LookupGet(x.PropertyName)(data);
                }
                command.Parameters.Add(parameter);
            }

            //--- ok
            return(Tuple.Create((DbCommand)command, output));
        }
        public void IDを設定するInsert文生成()
        {
            var actual1 = PrimitiveSql.CreateInsert(DbKind.SqlServer, typeof(Person), setIdentity: true);
            var actual2 = PrimitiveSql.CreateInsert <Person>(DbKind.SqlServer, setIdentity: true);
            var expect  =
                @"insert into dbo.Person
(
    Id,
    名前,
    Age,
    HasChildren
)
values
(
    @Id,
    @Name,
    next value for dbo.AgeSeq,
    @HasChildren
)";

            actual1.Is(expect);
            actual2.Is(expect);
        }
Exemple #8
0
        /// <summary>
        /// レコードを挿入し、そのレコードに自動採番されたIDを取得するSQLを生成します。
        /// </summary>
        /// <typeparam name="T">テーブルにマッピングされた型</typeparam>
        /// <returns>SQL文</returns>
        protected override string CreateInsertAndGetSql <T>()
        =>
        $@"{PrimitiveSql.CreateInsert<T>(this.DbKind)};
select last_insert_rowid() as Id;";
Exemple #9
0
        /// <summary>
        /// レコードを挿入し、そのレコードに自動採番されたIDを取得するSQLを生成します。
        /// </summary>
        /// <typeparam name="T">テーブルにマッピングされた型</typeparam>
        /// <returns>SQL文</returns>
        protected override string CreateInsertAndGetSql <T>()
        =>
        $@"{PrimitiveSql.CreateInsert<T>(this.DbKind)};
select cast(scope_identity() as bigint) as Id;";
        /// <summary>
        /// レコードを挿入し、そのレコードに自動採番されたIDを取得するSQLを生成します。
        /// </summary>
        /// <typeparam name="T">テーブルにマッピングされた型</typeparam>
        /// <returns>SQL文</returns>
        protected override string CreateInsertAndGetSql <T>()
        =>
        $@"{PrimitiveSql.CreateInsert<T>(this.DbKind)};
select @@IDENTITY as Id;";