Cuidados ao utilizar SqlBulkCopy
Alguns cuidados são necessários ao utilizar SqlBulkCopy, em especial verificar as constraints e o tratamento aos nulos, que devem ser feitos explicitamente em código para evitar problemas de consistência potencialmente muito custosos.
Considere as seguintes tabelas
create table Employer
(
EmployerId int not null constraint PK_Employer Primary Key
--Outras informações
)
create table Employee
(
EmployeeId int not null constraint PK_Employee Primary Key
--Outras informações
)
create table EmployerEmployee
(
EmployerId int not null constraint FK_EmployerEmployee_EmployerId
Foreign Key references Employer (EmployerId),
EmployeeId int not null constraint FK_EmployerEmployee_EmployeeId
Foreign Key references Employee (EmployeeId),
HireDate datetime null constraint df_EmployerEmployee default getdate(),
constraint PK_EmployerEmployee Primary Key (EmployerId, EmployeeId)
)
A princípio as relações extrangeiras (foreign keys) garantem que não exista nenhum Id inválido (ex.: Existe uma relação mas o EmployerId não existe na tabela Employer). Mas o comportamento padrão do SqlBulkCopy é ignorar essas constraints.
Então se utilizarmos o código abaixo, quaisquer valores poderão ser inseridos nas tabelas.
private static void InserRelation(int employerId, IEnumerable employeeIds)
{
using (var bulkCopy = new SqlBulkCopy(ConnectionString, ))
using (var table = new DataTable())
{
table.Columns.Add("EmployerId", typeof(int));
table.Columns.Add("EmployeeId", typeof(int));
table.Columns.Add("HireDate", typeof(double));
bulkCopy.DestinationTableName = "EmployerEmployee";
bulkCopy.BulkCopyTimeout = BulkTimeout;
bulkCopy.BatchSize = BulkBatchSize;
for (int i = 0; i < table.Columns.Count; i++)
{
bulkCopy.ColumnMappings.Add(table.Columns[i].ColumnName,
table.Columns[i].ColumnName);
}
foreach (var employeeId in employeeIds)
{
table.Rows.Add(employerId, employeeId, null);
if (table.Rows.Count >= bulkCopy.BatchSize)
{
bulkCopy.WriteToServer(table);
table.Rows.Clear();
}
}
bulkCopy.WriteToServer(table);
table.Rows.Clear();
}
}
Para garantir que os valores serão checados utilizar a opção SqlBulkCopyOptions.CheckConstraints. Deste modo:
using (var bulkCopy = new SqlBulkCopy(ConnectionString,
SqlBulkCopyOptions.CheckConstraints))
E mais...se checarmos os valores inseridos na coluna HireDate, veremos que o valores "null" passados foram desconsiderados e a constraint default foi utilizada em seu lugar. Para garantir os valores "null" combinar a opção utilizada com SqlBulkCopyOptions.KeepNulls. Desta forma:
using (var bulkCopy = new SqlBulkCopy(ConnectionString,
SqlBulkCopyOptions.CheckConstraints | SqlBulkCopyOptions.KeepNulls))
É claro que tudo isso vai depender da consistência e dos valores esperados no BD. Vale a pena testar as outras opções para não acabar com resultados inesperados.
Anteriormente, após cada artigo de nosso blog, havia uma seção de comentários e opções de compartilhamento simples.
Contudo, com a entrada em vigor da LGPD, a coleta de informações pessoais exige consentimento prévio, o que dificulta manter uma interação fluida. Além disso, provedores de comentários e ferramentas de moderação exigem coleta de dados, tornando-nos corresponsáveis ao incorporá-los em nosso site.
Paralelamente, decisões recentes (final de 2024) do STF aumentaram a responsabilidade dos proprietários de sites sobre o conteúdo postado por terceiros, exigindo remoção imediata de conteúdos potencialmente ofensivos, mesmo sem determinação judicial prévia.
Diante desse cenário ruim em termos de Liberdade de Expressão, optamos por encerrar a seção de comentários, visando cumprir a legislação e reduzir riscos operacionais.