コード例 #1
0
ファイル: BulkInserter.cs プロジェクト: goldenauge/framework
    public static int BulkInsertTable <T>(IEnumerable <T> entities,
                                          SqlBulkCopyOptions copyOptions = SafeDefaults,
                                          bool preSaving       = true,
                                          bool validateFirst   = true,
                                          bool disableIdentity = false,
                                          int?timeout          = null,
                                          string?message       = null)
        where T : Entity
    {
        using (HeavyProfiler.Log(nameof(BulkInsertTable), () => typeof(T).TypeName()))
        {
            if (message != null)
            {
                return(SafeConsole.WaitRows(message == "auto" ? $"BulkInsering {entities.Count()} {typeof(T).TypeName()}" : message,
                                            () => BulkInsertTable(entities, copyOptions, preSaving, validateFirst, disableIdentity, timeout, message: null)));
            }

            if (disableIdentity)
            {
                copyOptions |= SqlBulkCopyOptions.KeepIdentity;
            }

            if (copyOptions.HasFlag(SqlBulkCopyOptions.UseInternalTransaction))
            {
                throw new InvalidOperationException("BulkInsertDisableIdentity not compatible with UseInternalTransaction");
            }

            var list = entities.ToList();

            if (preSaving)
            {
                Saver.PreSaving(() => GraphExplorer.FromRoots(list));
            }

            if (validateFirst)
            {
                Validate <T>(list);
            }

            var  t = Schema.Current.Table <T>();
            bool disableIdentityBehaviour = copyOptions.HasFlag(SqlBulkCopyOptions.KeepIdentity);

            DataTable dt      = new DataTable();
            var       columns = t.Columns.Values.Where(c => !(c is SystemVersionedInfo.SqlServerPeriodColumn) && (disableIdentityBehaviour || !c.IdentityBehaviour)).ToList();
            foreach (var c in columns)
            {
                dt.Columns.Add(new DataColumn(c.Name, ConvertType(c.Type)));
            }

            using (disableIdentityBehaviour ? Administrator.DisableIdentity(t, behaviourOnly: true) : null)
            {
                foreach (var e in list)
                {
                    if (!e.IsNew)
                    {
                        throw new InvalidOperationException("Entites should be new");
                    }
                    t.SetToStrField(e);
                    dt.Rows.Add(t.BulkInsertDataRow(e));
                }
            }

            using (var tr = new Transaction())
            {
                Schema.Current.OnPreBulkInsert(typeof(T), inMListTable: false);

                Executor.BulkCopy(dt, columns, t.Name, copyOptions, timeout);

                foreach (var item in list)
                {
                    item.SetNotModified();
                }

                return(tr.Commit(list.Count));
            }
        }
    }