Я знаю, что приведенный ниже метод не предназначен для работы с какой-либо сущностью, и его использование не должно быть принудительным.
Я нашел метод расширения System.Data.Linq.Table, который использует SqlBulkCopy для вставки данных. Я пытаюсь адаптировать его к Entity Framework, но он выдает странное исключение, в то время как оригинал работает для классов данных Linq-To-Sql. До сих пор я не мог найти недостаток, это происходит с любой таблицей SQL в отображении 1-1. Не могли бы вы помочь мне?
public static class ObjectQueryExtensions
{
public static string GetName<TEntity>(
this ObjectQuery<TEntity> objectQuery)
where TEntity : class
{
var tableNameGroup = new Regex(@"FROM\s([^\s]*)\s"
, RegexOptions.IgnoreCase);
var sql = objectQuery.ToTraceString();
var tableNameGroupMatch = tableNameGroup.Match(sql);
return tableNameGroupMatch.Groups[1].Value;
}
public static void BulkInsert<TEntity>(
this ObjectQuery<TEntity> objectQuery
, IEnumerable<TEntity> items)
where TEntity : class
{
using (var dt = new DataTable())
{
var properties = typeof(TEntity)
.GetProperties()
.Where(property => property.Name != "EntityKey")
.Where(property => property.Name != "EntityState")
;
foreach (var property in properties)
{
dt.Columns.Add(property.Name
, Nullable.GetUnderlyingType(property.PropertyType)
?? property.PropertyType);
}
foreach (var t in items)
{
DataRow row = dt.NewRow();
foreach (var info in properties)
{
row[info.Name] = info.GetValue(t, null) ?? DBNull.Value;
}
dt.Rows.Add(row);
}
var entityConnection = (EntityConnection)objectQuery
.Context.Connection;
using (var sqlBulkCopy = new SqlBulkCopy(
entityConnection.StoreConnection.ConnectionString))
{
sqlBulkCopy.DestinationTableName = objectQuery.GetName();
sqlBulkCopy.WriteToServer(dt);
}
}
}
}
Исключение
Метод тестирования LinqExtensionsTest.ObjectQueryExtensionsTest.BulkInsertTest вызвал исключение: System.InvalidOperationException: данное значение типа Int64 из источника данных нельзя преобразовать в тип datetime указанного целевого столбца. ---> System.InvalidCastException: не удалось преобразовать значение параметра из Int64 в DateTime. ---> System.InvalidCastException: недопустимое приведение от 'Int64' к 'DateTime' ..
трассировка стека
System.Int64.System.IConvertible.ToDateTime (поставщик IFormatProvider)
System.Convert.ChangeType (значение объекта, тип преобразования типа, поставщик IFormatProvider)
System.Data.SqlClient.SqlParameter.CoerceValue (значение объекта, MetaType destinationType)
System.Data.SqlClient.SqlParameter.CoerceValue (значение объекта, MetaType destinationType)
System.Data.SqlClient.SqlBulkCopy.ConvertValue (значение объекта, метаданные _SqlMetaData)
System.Data.SqlClient.SqlBulkCopy.ConvertValue (значение объекта, метаданные _SqlMetaData)
System.Data.SqlClient.SqlBulkCopy.WriteToServerInternal ()
System.Data.SqlClient.SqlBulkCopy.WriteRowSourceToServer (Int32 columnCount)
System.Data.SqlClient.SqlBulkCopy.WriteToServer (таблица DataTable, DataRowState rowState)
System.Data.SqlClient.SqlBulkCopy.WriteToServer (таблица DataTable)
LinqExtensions.ObjectQueryExtensions.BulkInsert [TEntity] (ObjectQuery 1 objectQuery, IEnumerable
1 элементов) в LinqExtensions \ LinqExtensions \ ObjectQueryExtensions.cs: строка 60
LinqExtensionsTest.ObjectQueryExtensionsTest.BulkInsertTest () в LinqExtensions \ LinqExtensionsTest \ ObjectQueryExtensionsTest.cs: строка 88