예제 #1
0
 private void IdInsertOn(SqlCeTransaction localTrans, int idOrdinal)
 {
     if (_keepIdentity && idOrdinal >= 0)
     {
         using (var idCmd = AdoNetUtils.CreateCommand(_conn, localTrans, string.Format(CultureInfo.InvariantCulture, "SET IDENTITY_INSERT [{0}] ON", DestinationTableName)))
         {
             idCmd.ExecuteNonQuery();
         }
         if (_trans == null)
         {
             _autoIncNext = SqlCeBulkCopyTableHelpers.GetAutoIncNext(_conn, DestinationTableName);
         }
     }
 }
예제 #2
0
        internal static List <KeyValuePair <int, int> > Create(SqlCeConnection conn, ISqlCeBulkCopyInsertAdapter adapter, SqlCeBulkCopyOptions copyOptions, string tableName)
        {
            var keepNulls = SqlCeBulkCopyTableHelpers.IsCopyOption(SqlCeBulkCopyOptions.KeepNulls, copyOptions);
            var retVal    = new List <KeyValuePair <int, int> >();
            //we use this to determine if we throw an error while building maps.
            int idOrdinal = SqlCeBulkCopyTableHelpers.IdentityOrdinalIgnoreOptions(conn, tableName);

            var destColumnData = DestinationTableDefaultMetadata.GetDataForTable(conn, tableName);

            //we are going to validate all of the columns but if we don't map then we will not set the HasMappings
            //A map is defined as
            //1. any column that the column order is changed
            //2. field exists in the dest but not the source and the dest has a default.
            //3. Identity column that is not 0 ?? we may be able to remove this one.

            //we only really care about the destination columns being mapped. If too many columns exist do we really care????

            var sourceColumns = GetSourceColumns(adapter);

            for (int destIndex = 0; destIndex < destColumnData.Count; destIndex++)
            {
                var destColumn  = destColumnData[destIndex];
                var sourceIndex = sourceColumns.IndexOf(destColumn.ColumnName);
                //see if the source is the same as the destination ordinal
                //if (destIndex != sourceIndex) //we have a map if we care later

                //If the source index is -1 and the dest does not allow nulls or has a default, it is an error

                if (sourceIndex < 0)
                {
                    //either we allow nulls or the ordinal is the index and therefore it is valid
                    if (!destColumnData[destIndex].HasDefault && ((!destColumnData[destIndex].IsNullable && !keepNulls) && idOrdinal != destIndex))
                    {
                        //var error = destColumnData[destIndex].HasDefault + " " + destColumnData[destIndex].IsNullable + " " + keepNulls + " " + idOrdinal + " " + destIndex;
                        throw new ApplicationException(string.Format("Source column '{0}' does not exist and destination does not allow nulls.", destColumn.ColumnName));
                    }
                }

                retVal.Add(new KeyValuePair <int, int>(sourceIndex, destIndex));
            }

            return(retVal);
        }
예제 #3
0
        private void ResetSeed(int totalRows)
        {
            if (totalRows == 0)
            {
                return;
            }

            if (!_keepIdentity)
            {
                return;
            }

            //Cannot run re-seed when using user supplied transaction, so fail silently
            if (_keepIdentity && _trans != null)
            {
                return;
            }

            var newAutoIncNext = SqlCeBulkCopyTableHelpers.GetAutoIncNext(_conn, DestinationTableName);

            if (_autoIncNext != newAutoIncNext)
            {
                return;
            }

            using (var transact = _conn.BeginTransaction())
            {
                // Get Identity column
                string idCol = null;
                using (var ainCmd = AdoNetUtils.CreateCommand(_conn, transact, string.Format(CultureInfo.InvariantCulture,
                                                                                             "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '{0}' AND AUTOINC_INCREMENT IS NOT NULL", DestinationTableName)))
                {
                    object res = ainCmd.ExecuteScalar();
                    if (res != null)
                    {
                        idCol = (string)res;
                    }
                }
                if (string.IsNullOrEmpty(idCol))
                {
                    return;
                }

                // Get Max value if the column
                long?maxVal = null;
                using (var ainCmd = AdoNetUtils.CreateCommand(_conn, transact, string.Format(CultureInfo.InvariantCulture,
                                                                                             "SELECT CAST(MAX([{0}]) AS bigint) FROM [{1}]", idCol, DestinationTableName)))
                {
                    object res = ainCmd.ExecuteScalar();
                    if (res != null)
                    {
                        maxVal = (long)res;
                    }
                }
                if (!maxVal.HasValue)
                {
                    return;
                }

                //Reseed
                using (var ainCmd = AdoNetUtils.CreateCommand(_conn, transact, string.Format(CultureInfo.InvariantCulture,
                                                                                             "ALTER TABLE [{0}] ALTER COLUMN [{1}] IDENTITY ({2},1);", DestinationTableName, idCol, maxVal + 1)))
                {
                    ainCmd.ExecuteNonQuery();
                }
                transact.Commit();
            }
        }
예제 #4
0
        private void WriteToServer(ISqlCeBulkCopyInsertAdapter adapter)
        {
            CheckDestination();

            if (_conn.State != ConnectionState.Open)
            {
                _conn.Open();
            }

            GetAndDropConstraints();

            List <KeyValuePair <int, int> > map;
            int totalRows = 0;
            SqlCeTransaction localTrans = _trans ?? _conn.BeginTransaction();

            if (ColumnMappings.Count > 0)
            {
                //mapping are set, and should be validated
                map = ColumnMappings.ValidateCollection(_conn, localTrans, adapter, _keepNulls, _destination);
            }
            else
            {
                //create default column mappings
                map = SqlCeBulkCopyColumnMappingCollection.Create(_conn, localTrans, adapter, _keepNulls, _destination);
            }

            using (var cmd = new SqlCeCommand(_destination, _conn, localTrans))
            {
                cmd.CommandType = CommandType.TableDirect;
                using (var rs = cmd.ExecuteResultSet(ResultSetOptions.Updatable))
                {
                    var idOrdinal = SqlCeBulkCopyTableHelpers.IdentityOrdinal(_conn, localTrans, _destination);
                    var rec       = rs.CreateRecord();

                    var rowCounter = 0;
                    IdInsertOn(localTrans, idOrdinal);

                    //Converting to an array removed the perf issue of a list and foreach statement.
                    var cm = map.ToArray();

                    while (adapter.Read())
                    {
                        if (adapter.SkipRow())
                        {
                            continue;
                        }

                        for (var i = 0; i < cm.Length; i++)
                        {
                            //caching the values this way do not cause a perf issue.
                            var sourceIndex = cm[i].Key;
                            var destIndex   = cm[i].Value;

                            // Let the destination assign identity values
                            if (!_keepIdentity && destIndex == idOrdinal)
                            {
                                continue;
                            }

                            //determine if we should ever allow this in the map.
                            if (sourceIndex < 0)
                            {
                                continue;
                            }

                            var value = sourceIndex > -1 ? adapter.Get(sourceIndex) : null;

                            if (value != null && value.GetType() != DbNullType)
                            {
                                rec.SetValue(destIndex, value);
                            }
                            else
                            {
                                //we can't write to an auto number column so continue
                                if (_keepNulls && destIndex == idOrdinal)
                                {
                                    continue;
                                }

                                if (_keepNulls)
                                {
                                    rec.SetValue(destIndex, DBNull.Value);
                                }
                                else
                                {
                                    rec.SetDefault(destIndex);
                                }
                            }
                        }
                        rowCounter++;
                        totalRows++;
                        try
                        {
                            rs.Insert(rec);
                        }
                        catch (SqlCeException ex)
                        {
                            if (ex.NativeError == 25016 && _ignoreDuplicateErrors) //A duplicate value cannot be inserted into a unique index.
                            {
                                System.Diagnostics.Trace.TraceWarning("SqlCeBulkCopy: Duplicate value error was ignored");
                                continue;
                            }
                            else
                            {
                                throw;
                            }
                        }
                        // Fire event if needed
                        if (RowsCopied != null && _notifyAfter > 0 && rowCounter == _notifyAfter)
                        {
                            FireRowsCopiedEvent(totalRows);
                            rowCounter = 0;
                        }
                    }
                    IdInsertOff(localTrans, idOrdinal);
                    if (RowsCopied != null)
                    {
                        FireRowsCopiedEvent(totalRows);
                    }
                }
            }

            //if we have our own transaction, we will commit it
            if (_trans == null)
            {
                localTrans.Commit(CommitMode.Immediate);
                localTrans.Dispose();
            }
            ResetSeed(totalRows);
            RestoreConstraints();
        }
예제 #5
0
파일: SqlCeBulkCopy.cs 프로젝트: OlehR/BRB3
        private void WriteToServer(ISqlCeBulkCopyInsertAdapter adapter)
        {
            CheckDestination();

            if (conn.State != ConnectionState.Open)
            {
                conn.Open();
            }

            List <KeyValuePair <int, int> > mappings = null;

            if (Mappings.Count > 0)
            {
                //mapping are set, and should be validated
                mappings = Mappings.ValidateCollection(conn, adapter, options, destination);
            }
            else
            {
                //create default column mappings
                mappings = SqlCeBulkCopyColumnMappingCollection.Create(conn, adapter, options, destination);
            }

            SqlCeTransaction localTrans = trans ?? conn.BeginTransaction();

            using (SqlCeCommand cmd = new SqlCeCommand(destination, conn, localTrans))
            {
                cmd.CommandType = CommandType.TableDirect;
                using (SqlCeResultSet rs = cmd.ExecuteResultSet(ResultSetOptions.Updatable))
                {
                    int idOrdinal            = SqlCeBulkCopyTableHelpers.IdentityOrdinal(conn, options, destination);
                    SqlCeUpdatableRecord rec = rs.CreateRecord();

                    int rowCounter = 0;
                    int totalRows  = 0;
                    IdInsertOn();

                    //Converting to an array removed the perf issue of a list and foreach statement.
                    var cm = mappings.ToArray();

                    while (adapter.Read())
                    {
                        if (adapter.SkipRow())
                        {
                            continue;
                        }

                        for (int i = 0; i < cm.Length; i++)
                        {
                            //caching the values this way do not cause a perf issue.
                            var sourceIndex = cm[i].Key;
                            var destIndex   = cm[i].Value;

                            // Let the destination assign identity values
                            if (!keepIdentity && destIndex == idOrdinal)
                            {
                                continue;
                            }

                            //determine if we should ever allow this in the map.
                            if (sourceIndex < 0)
                            {
                                continue;
                            }

                            var value = sourceIndex > -1 ? adapter.Get(sourceIndex) : null;

                            if (value != null && value.GetType() != DbNullType)
                            {
                                rec.SetValue(destIndex, value);
                            }
                            else
                            {
                                //we can't write to an auto number column so continue
                                if (keepNulls && destIndex == idOrdinal)
                                {
                                    continue;
                                }

                                if (keepNulls)
                                {
                                    rec.SetValue(destIndex, DBNull.Value);
                                }
                                else
                                {
                                    rec.SetDefault(destIndex);
                                }
                            }
                            // Fire event if needed
                            if (notifyAfter > 0 && rowCounter == notifyAfter)
                            {
                                FireRowsCopiedEvent(totalRows);
                                rowCounter = 0;
                            }
                        }
                        rowCounter++;
                        totalRows++;
                        rs.Insert(rec);
                    }
                    IdInsertOff();
                }
            }

            //if we have our own transaction, we will commit it
            if (trans == null)
            {
                localTrans.Commit(CommitMode.Immediate);
            }
        }