mirror of
https://github.com/DapperLib/Dapper.git
synced 2026-10-17 05:12:13 +08:00
6ab170c160
* initial net5.0 tweaks; also fix current IDE warnings * lib updates and fixes * more cleanup * fix snafu * skip locals init * disable xunit shadow copy in tests * test records * explore scenario that currently works re #1571
151 lines
5.7 KiB
C#
151 lines
5.7 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Data;
|
|
using System.Data.Common;
|
|
using System.Linq.Expressions;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Dapper.ProviderTools.Internal;
|
|
|
|
namespace Dapper.ProviderTools
|
|
{
|
|
/// <summary>
|
|
/// Provides provider-agnostic access to bulk-copy services
|
|
/// </summary>
|
|
public abstract class BulkCopy : IDisposable
|
|
{
|
|
/// <summary>
|
|
/// Attempt to create a BulkCopy instance for the connection provided
|
|
/// </summary>
|
|
public static BulkCopy? TryCreate(DbConnection connection)
|
|
{
|
|
if (connection == null) return null;
|
|
var type = connection.GetType();
|
|
if (!s_bcpFactory.TryGetValue(type, out var func))
|
|
{
|
|
s_bcpFactory[type] = func = CreateBcpFactory(type);
|
|
}
|
|
var obj = func?.Invoke(connection);
|
|
return DynamicBulkCopy.Create(obj);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a BulkCopy instance for the connection provided
|
|
/// </summary>
|
|
public static BulkCopy Create(DbConnection connection)
|
|
{
|
|
var bcp = TryCreate(connection);
|
|
if (bcp == null)
|
|
{
|
|
if (connection == null) throw new ArgumentNullException(nameof(connection));
|
|
throw new NotSupportedException("Unable to create BulkCopy for " + connection.GetType().FullName);
|
|
}
|
|
return bcp;
|
|
}
|
|
|
|
///// <summary>
|
|
///// Provide an external registration for a given connection type
|
|
///// </summary>
|
|
//public static void Register(Type type, Func<DbConnection, BulkCopy> factory)
|
|
//{
|
|
// throw new NotImplementedException();
|
|
//}
|
|
|
|
private static readonly ConcurrentDictionary<Type, Func<DbConnection, object>?> s_bcpFactory
|
|
= new ConcurrentDictionary<Type, Func<DbConnection, object>?>();
|
|
|
|
internal static Func<DbConnection, object>? CreateBcpFactory(Type connectionType)
|
|
{
|
|
try
|
|
{
|
|
var match = Regex.Match(connectionType.Name, "^(.+)Connection$");
|
|
if (match.Success)
|
|
{
|
|
var prefix = match.Groups[1].Value;
|
|
var bcpType = connectionType.Assembly.GetType($"{connectionType.Namespace}.{prefix}BulkCopy");
|
|
if (bcpType != null)
|
|
{
|
|
var ctor = bcpType.GetConstructor(new[] { connectionType });
|
|
if (ctor == null) return null;
|
|
|
|
var p = Expression.Parameter(typeof(DbConnection), "conn");
|
|
var body = Expression.New(ctor, Expression.Convert(p, connectionType));
|
|
return Expression.Lambda<Func<DbConnection, object>>(body, p).Compile();
|
|
}
|
|
}
|
|
}
|
|
catch { }
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Name of the destination table on the server.
|
|
/// </summary>
|
|
public abstract string DestinationTableName { get; set; }
|
|
/// <summary>
|
|
/// Write a set of data to the server
|
|
/// </summary>
|
|
public abstract void WriteToServer(DataTable source);
|
|
/// <summary>
|
|
/// Write a set of data to the server
|
|
/// </summary>
|
|
public abstract void WriteToServer(DataRow[] source);
|
|
/// <summary>
|
|
/// Write a set of data to the server
|
|
/// </summary>
|
|
public abstract void WriteToServer(IDataReader source);
|
|
/// <summary>
|
|
/// Write a set of data to the server
|
|
/// </summary>
|
|
public abstract Task WriteToServerAsync(DbDataReader source, CancellationToken cancellationToken = default);
|
|
/// <summary>
|
|
/// Write a set of data to the server
|
|
/// </summary>
|
|
public abstract Task WriteToServerAsync(DataTable source, CancellationToken cancellationToken = default);
|
|
/// <summary>
|
|
/// Write a set of data to the server
|
|
/// </summary>
|
|
public abstract Task WriteToServerAsync(DataRow[] source, CancellationToken cancellationToken = default);
|
|
/// <summary>
|
|
/// Add a mapping between two columns by name
|
|
/// </summary>
|
|
public abstract void AddColumnMapping(string sourceColumn, string destinationColumn);
|
|
/// <summary>
|
|
/// Add a mapping between two columns by position
|
|
/// </summary>
|
|
public abstract void AddColumnMapping(int sourceColumn, int destinationColumn);
|
|
/// <summary>
|
|
/// The underlying untyped object providing the bulk-copy service
|
|
/// </summary>
|
|
public abstract object Wrapped { get; }
|
|
|
|
/// <summary>
|
|
/// Enables or disables streaming from a data-reader
|
|
/// </summary>
|
|
public bool EnableStreaming { get; set; }
|
|
/// <summary>
|
|
/// Number of rows in each batch
|
|
/// </summary>
|
|
public int BatchSize { get; set; }
|
|
/// <summary>
|
|
/// Number of seconds for the operation to complete before it times out.
|
|
/// </summary>
|
|
public int BulkCopyTimeout { get; set; }
|
|
|
|
/// <summary>
|
|
/// Release any resources associated with this instance
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Release any resources associated with this instance
|
|
/// </summary>
|
|
protected abstract void Dispose(bool disposing);
|
|
}
|
|
}
|