我当前的项目是.net 5,我已经升级到.net 6版本。 早些时候,代码工作正常,但升级后,此代码似乎无法工作。
public async Task AddBulkAsync(List<T> entityList)
{
try
{
if (entityList.Count > 0)
{
using (var sqlBulkCopy = GetSqlBulkCopy(this._dbContext, this._dbContext.Database.CurrentTransaction))
{
sqlBulkCopy.BatchSize = 10000;
sqlBulkCopy.BulkCopyTimeout = 1800;
var dataTable = GetDataTable(entityList, sqlBulkCopy);
await sqlBulkCopy.WriteToServerAsync(dataTable);
}
}
}
catch (Exception)
{
throw;
}
}
internal DataTable GetDataTable<T>(IList<T> entities, SqlBulkCopy sqlBulkCopy)
{
var dataTable = new DataTable();
var columnsDict = new Dictionary<string, object>();
var ownedEntitiesMappedProperties = new HashSet<string>();
var type = entities[0].GetType();
var entityType = this._dbContext.Model.FindEntityType(type);
//var entityPropertiesDict = entityType.GetProperties().Where(a => tableInfo.PropertyColumnNamesDict.ContainsKey(a.Name)).ToDictionary(a => a.Name, a => a);
var entityPropertiesDict = entityType.GetProperties().ToDictionary(a => a.Name, a => a);
var entityNavigationOwnedDict = entityType.GetNavigations().Where(a => a.GetTargetType().IsOwned()).ToDictionary(a => a.Name, a => a);
var properties = type.GetProperties();
// var discriminatorColumn = tableInfo.ShadowProperties.Count == 0 ? null : tableInfo.ShadowProperties.ElementAt(0);
foreach (var property in properties)
{
if (entityPropertiesDict.ContainsKey(property.Name))
{
var propertyEntityType = entityPropertiesDict[property.Name];
string columnName = propertyEntityType.GetColumnName();
// var isConvertible = tableInfo.ConvertibleProperties.ContainsKey(columnName);
var propertyType = property.PropertyType;
var underlyingType = Nullable.GetUnderlyingType(propertyType);
if (underlyingType != null)
{
propertyType = underlyingType;
}
dataTable.Columns.Add(columnName, propertyType);
columnsDict.Add(property.Name, null);
}
}
foreach (var entity in entities)
{
foreach (var property in properties)
{
if (entityPropertiesDict.ContainsKey(property.Name))
{
var propertyValue = property.GetValue(entity, null);
if (property.PropertyType == typeof(Guid) && (Guid)propertyValue == default(Guid))
{
propertyValue = Guid.NewGuid();
}
columnsDict[property.Name] = propertyValue;
}
}
var record = columnsDict.Values.ToArray();
dataTable.Rows.Add(record);
}
foreach (DataColumn item in dataTable.Columns) //Add mapping
{
sqlBulkCopy.ColumnMappings.Add(item.ColumnName, item.ColumnName);
}
string schema = entityType.GetSchema() != null ? entityType.GetSchema() : "dbo";
dataTable.TableName = schema + "." + entityType.GetTableName();
sqlBulkCopy.DestinationTableName = dataTable.TableName;
return dataTable;
}
private SqlBulkCopy GetSqlBulkCopy(DbContext dbContext, IDbContextTransaction transaction)
{
var sqlConnection = dbContext.Database.GetDbConnection().ConnectionString;
if (transaction == null)
{
//return new SqlBulkCopy(sqlConnection, sqlBulkCopyOptions, null);
return new SqlBulkCopy(sqlConnection, SqlBulkCopyOptions.CheckConstraints);
}
else
{
var sqlTransaction = (SqlTransaction)transaction.GetDbTransaction();
//return new SqlBulkCopy(sqlConnection, sqlBulkCopyOptions, sqlTransaction);
return new SqlBulkCopy(sqlConnection, SqlBulkCopyOptions.CheckConstraints);
}
}
这似乎没有按预期工作
await sqlBulkCopy.WriteToServerAsync(dataTable);
我尝试用非异步方法实现
sqlBulkCopy.WriteToServer(dataTable);
但仍然出现同样的问题
它返回一个错误
“发生一个或多个错误。(用户“Devadmin”登录失败。)” 我已经尝试过 Task.Run 方法,它不会返回任何错误,但数据不会插入到表中。
Task.Run(async () => await sqlBulkCopy.WriteToServerAsync(dataTable));
请有人帮助我解决这个问题。
问题是
DbConnection
已经打开了。因此,当您尝试检索连接字符串时,密码已被擦除。
您可以将
persist security info=true
添加到字符串中,但我建议不要这样做。
相反,重写您的
GetSqlBulkCopy
函数,该函数处理事务的方式从根本上被破坏了,因此它现在重用它接收到的连接对象,而不仅仅是连接字符串。
private SqlBulkCopy GetSqlBulkCopy(SqlConnection connection, DbContext dbContext)
{
var sqlTransaction = _dbContext.Database.CurrentTransaction.GetDbTransaction() as SqlTransaction;
return new SqlBulkCopy(sqlConnection, SqlBulkCopyOptions.CheckConstraints, sqltransaction);
}
然后
var sqlConnection = (SqlConnection)dbContext.Database.GetDbConnection();
var wasOpen = sqlConnection.ConnectionState == ConnectionState.Open
try
{
using (var sqlBulkCopy = GetSqlBulkCopy(sqlConnection, this._dbContext))
{
//etc
if (!wasOpen)
await sqlConnection.OpenAsync();
// etc
}
}
finally
{
if (!wasOpen)
sqlConnection.Close();
}
而不是在字符串中添加
persist security info=true
。我们可以使用以下代码。
var sqlConnectionString = SqlConnectionToConnectionString((SqlConnection)this._dbContext.Database.GetDbConnection());
var sqlConnection = new SqlConnection(sqlConnectionString);
var wasOpen = sqlConnection.State == ConnectionState.Open;
try
{
using (var sqlBulkCopy = new SqlBulkCopy(sqlConnectionString, SqlBulkCopyOptions.CheckConstraints))
{
if (!wasOpen)
await sqlConnection.OpenAsync();
sqlBulkCopy.BatchSize = 10000;
sqlBulkCopy.BulkCopyTimeout = 1800;
var dataTable = GetDataTable(entityList, sqlBulkCopy);
await sqlBulkCopy.WriteToServerAsync(dataTable);
}
}
finally
{
if (!wasOpen)
sqlConnection.Close();
}