Skip to content

Commit

Permalink
Merge pull request #8 from ErikEJ/issue-7
Browse files Browse the repository at this point in the history
Issue 7
  • Loading branch information
ErikEJ committed Dec 27, 2017
2 parents 140389d + 911a158 commit 8e06ce8
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 61 deletions.
4 changes: 2 additions & 2 deletions src/Properties/AssemblyInfo.cs
Expand Up @@ -18,8 +18,8 @@
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("1c320ebd-6449-44eb-b727-fae56de65eaa")]

[assembly: AssemblyVersion("2.1.6.14")]
[assembly: AssemblyVersion("2.1.6.15")]
#if PocketPC
#else
[assembly: AssemblyFileVersion("2.1.6.14")]
[assembly: AssemblyFileVersion("2.1.6.15")]
#endif
71 changes: 40 additions & 31 deletions src/SqlCeBulkCopy.cs
Expand Up @@ -26,14 +26,14 @@ public class SqlCeBulkCopy : IDisposable
private readonly SqlCeTransaction _trans;
private readonly bool _ownsConnection;
private bool _ownsTransaction;
private readonly bool _keepNulls;
private readonly bool _keepIdentity;
private bool _keepNulls;
private bool _keepIdentity;
private bool _ignoreDuplicateErrors;
private string _destination;
private readonly SqlCeBulkCopyOptions _sqlCeBulkCopyOptions;
#if PocketPC
#else
private List<Constraint> _savedConstraints;
private readonly bool _disableConstraints;
private bool _disableConstraints;
#endif
/// <summary>
/// Initializes a new instance of the SqlCeBulkCopy class using the specified open instance of SqlCeConnection.
Expand Down Expand Up @@ -62,13 +62,7 @@ public SqlCeBulkCopy(SqlCeConnection connection, SqlCeTransaction transaction)
public SqlCeBulkCopy(SqlCeConnection connection, SqlCeBulkCopyOptions copyOptions)
{
_conn = connection;
_sqlCeBulkCopyOptions = copyOptions;
_keepNulls = IsCopyOption(SqlCeBulkCopyOptions.KeepNulls);
_keepIdentity = IsCopyOption(SqlCeBulkCopyOptions.KeepIdentity);
#if PocketPC
#else
_disableConstraints = IsCopyOption(SqlCeBulkCopyOptions.DisableConstraints);
#endif
SetOptions(copyOptions);
}

/// <summary>
Expand All @@ -81,13 +75,7 @@ public SqlCeBulkCopy(SqlCeConnection connection, SqlCeBulkCopyOptions copyOption
{
_conn = connection;
_trans = transaction;
_sqlCeBulkCopyOptions = copyOptions;
_keepNulls = IsCopyOption(SqlCeBulkCopyOptions.KeepNulls);
_keepIdentity = IsCopyOption(SqlCeBulkCopyOptions.KeepIdentity);
#if PocketPC
#else
_disableConstraints = IsCopyOption(SqlCeBulkCopyOptions.DisableConstraints);
#endif
SetOptions(copyOptions);
}

/// <summary>
Expand All @@ -108,13 +96,7 @@ public SqlCeBulkCopy(string connectionString, SqlCeBulkCopyOptions copyOptions)
{
_conn = new SqlCeConnection(connectionString);
_ownsConnection = true;
_sqlCeBulkCopyOptions = copyOptions;
_keepNulls = IsCopyOption(SqlCeBulkCopyOptions.KeepNulls);
_keepIdentity = IsCopyOption(SqlCeBulkCopyOptions.KeepIdentity);
#if PocketPC
#else
_disableConstraints = IsCopyOption(SqlCeBulkCopyOptions.DisableConstraints);
#endif
SetOptions(copyOptions);
}

/// <summary>
Expand Down Expand Up @@ -260,6 +242,18 @@ public void WriteToServer(IEnumerable collection, Type elementType)
}
}
#endif

private void SetOptions(SqlCeBulkCopyOptions options)
{
_keepNulls = IsCopyOption(SqlCeBulkCopyOptions.KeepNulls, options);
_keepIdentity = IsCopyOption(SqlCeBulkCopyOptions.KeepIdentity, options);
_ignoreDuplicateErrors = IsCopyOption(SqlCeBulkCopyOptions.IgnoreDuplicateErrors, options);
#if PocketPC
#else
_disableConstraints = IsCopyOption(SqlCeBulkCopyOptions.DisableConstraints, options);
#endif
}

private void WriteToServer(ISqlCeBulkCopyInsertAdapter adapter)
{
CheckDestination();
Expand All @@ -278,12 +272,12 @@ private void WriteToServer(ISqlCeBulkCopyInsertAdapter adapter)
if (ColumnMappings.Count > 0)
{
//mapping are set, and should be validated
map = ColumnMappings.ValidateCollection(_conn, localTrans, adapter, _sqlCeBulkCopyOptions, _destination);
map = ColumnMappings.ValidateCollection(_conn, localTrans, adapter, _keepNulls, _destination);
}
else
{
//create default column mappings
map = SqlCeBulkCopyColumnMappingCollection.Create(_conn, localTrans, adapter, _sqlCeBulkCopyOptions, _destination);
map = SqlCeBulkCopyColumnMappingCollection.Create(_conn, localTrans, adapter, _keepNulls, _destination);
}

using (var cmd = new SqlCeCommand(_destination, _conn, localTrans))
Expand Down Expand Up @@ -340,12 +334,27 @@ private void WriteToServer(ISqlCeBulkCopyInsertAdapter adapter)
rec.SetDefault(destIndex);
}
}
// Fire event if needed

}
rowCounter++;
totalRows++;
rs.Insert(rec);
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);
Expand Down Expand Up @@ -511,9 +520,9 @@ private void FireRowsCopiedEvent(long rowsCopied)
OnRowsCopied(args);
}

private bool IsCopyOption(SqlCeBulkCopyOptions copyOption)
private bool IsCopyOption(SqlCeBulkCopyOptions copyOption, SqlCeBulkCopyOptions options)
{
return ((_sqlCeBulkCopyOptions & copyOption) == copyOption);
return ((options & copyOption) == copyOption);
}

#region IDisposable Members
Expand Down
11 changes: 5 additions & 6 deletions src/SqlCeBulkCopyMappingCollection.cs
Expand Up @@ -77,9 +77,8 @@ internal SqlCeBulkCopyColumnMappingCollection()

#region other methods

internal static List<KeyValuePair<int, int>> Create(SqlCeConnection conn, SqlCeTransaction transaction, ISqlCeBulkCopyInsertAdapter adapter, SqlCeBulkCopyOptions copyOptions, string tableName)
internal static List<KeyValuePair<int, int>> Create(SqlCeConnection conn, SqlCeTransaction transaction, ISqlCeBulkCopyInsertAdapter adapter, bool keepNulls, 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.IdentityOrdinal(conn, transaction, tableName);
Expand Down Expand Up @@ -121,7 +120,7 @@ internal SqlCeBulkCopyColumnMappingCollection()
return retVal;
}

internal List<KeyValuePair<int, int>> ValidateCollection(SqlCeConnection conn, SqlCeTransaction transaction, ISqlCeBulkCopyInsertAdapter adapter, SqlCeBulkCopyOptions copyOptions, string tableName)
internal List<KeyValuePair<int, int>> ValidateCollection(SqlCeConnection conn, SqlCeTransaction transaction, ISqlCeBulkCopyInsertAdapter adapter, bool keepNulls, string tableName)
{
if (Count > 0)
{
Expand All @@ -133,8 +132,8 @@ internal SqlCeBulkCopyColumnMappingCollection()
{
var sourceColumnName = (mapping.SourceColumn ?? string.Empty).ToUpper(CultureInfo.InvariantCulture);
var destColumnName = (mapping.DestinationColumn ?? string.Empty).ToUpper(CultureInfo.InvariantCulture);
int sourceIndex = -1;
int destIndex = -1;
int sourceIndex;
int destIndex;

//verify if we have a source column name that it exists
if (!string.IsNullOrEmpty(sourceColumnName))
Expand Down Expand Up @@ -204,7 +203,7 @@ internal SqlCeBulkCopyColumnMappingCollection()
}
else
{
return Create(conn, transaction, adapter, copyOptions, tableName);
return Create(conn, transaction, adapter, keepNulls, tableName);
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/SqlCeBulkCopyOptions.cs
Expand Up @@ -30,5 +30,9 @@ public enum SqlCeBulkCopyOptions
/// Preserve null values in the destination table regardless of the settings for default values. When not specified, null values are replaced by default values where applicable.
/// </summary>
KeepNulls = 0x8,
/// <summary>
/// Ignores error 25016 - A duplicate value cannot be inserted into a unique index
/// </summary>
IgnoreDuplicateErrors = 0x16
}
}
5 changes: 0 additions & 5 deletions src/SqlCeBulkCopyTableHelpers.cs
Expand Up @@ -35,10 +35,5 @@ internal static long GetAutoIncNext(SqlCeConnection conn, string destinationTabl
return 0;
}
}

internal static bool IsCopyOption(SqlCeBulkCopyOptions options, SqlCeBulkCopyOptions copyOption)
{
return ((options & copyOption) == options);
}
}
}
15 changes: 2 additions & 13 deletions src/SqlCeRowsCopiedEventArgs.cs
Expand Up @@ -8,8 +8,7 @@ namespace ErikEJ.SqlCe
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Ce")]
public class SqlCeRowsCopiedEventArgs : EventArgs
{
private long _rowsCopied;
private bool _abort;
private readonly long _rowsCopied;

/// <summary>
/// Represents the set of arguments passed to the SqlCeRowsCopiedEventHandler.
Expand All @@ -33,16 +32,6 @@ public long RowsCopied
/// <summary>
/// Gets or sets a value that indicates whether the bulk copy operation should be aborted.
/// </summary>
public bool Abort
{
get
{
return _abort;
}
set
{
_abort = value;
}
}
public bool Abort { get; set; }
}
}
22 changes: 18 additions & 4 deletions src/Test/SqlCeBulkCopyTest.cs
Expand Up @@ -19,6 +19,7 @@ private enum SchemaType
{
NoConstraints,
FullConstraints,
FullConstraintsDuplicateRows,
FullNoIdentity,
DataReaderTest,
DataReaderTestMapped,
Expand Down Expand Up @@ -56,6 +57,8 @@ public void ExerciseEngineWithTable()

RunDataTableTest(10000, SchemaType.FullConstraints, true);

RunDataTableTest(10000, SchemaType.FullConstraintsDuplicateRows, true);

//RunDataTableTestNoKeepId(10000, SchemaType.FullNoIdentity, false);
}

Expand Down Expand Up @@ -123,6 +126,10 @@ private void RunDataTableTest(int recordCount, SchemaType schemaType, bool keepN
testTable.Rows.Add(new object[] { 4 + i, Guid.NewGuid().ToString() });
}
}
if (schemaType == SchemaType.FullConstraintsDuplicateRows)
{
testTable.Rows.Add(new object[] { 4, Guid.NewGuid().ToString() });
}
RunBulkCopy(schemaType, keepNulls, testTable);
}
}
Expand Down Expand Up @@ -236,15 +243,21 @@ private static void RunBulkCopy(SchemaType schemaType, bool keepNulls, DataTable
case SchemaType.FullConstraints:
options = SqlCeBulkCopyOptions.KeepIdentity;
break;
default:
case SchemaType.FullConstraintsDuplicateRows:
options = SqlCeBulkCopyOptions.KeepIdentity;
break;
}
if (keepNulls)
{
options = options |= SqlCeBulkCopyOptions.KeepNulls;
options = options |= SqlCeBulkCopyOptions.KeepNulls;
}

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

if (schemaType == SchemaType.FullConstraintsDuplicateRows)
{
options = options |= SqlCeBulkCopyOptions.IgnoreDuplicateErrors;
}

var sw = new Stopwatch();
sw.Start();

using (SqlCeBulkCopy bc = new SqlCeBulkCopy(connectionString, options))
Expand Down Expand Up @@ -285,6 +298,7 @@ private static void CreateDatabase(SchemaType schemaType)

break;
case SchemaType.FullConstraints:
case SchemaType.FullConstraintsDuplicateRows:
cmd.CommandText = "CREATE TABLE [Shippers] ([ShipperID] int NOT NULL IDENTITY (1,1), [CompanyName] nvarchar(40) NULL DEFAULT N'ABC');";
cmd.ExecuteNonQuery();

Expand Down

0 comments on commit 8e06ce8

Please sign in to comment.