Nesta notícia analisamos o System.Data no .NET Core 3.0. Agora, a atenção será voltada para o System.Data.SqlClient, o driver do SQL Server.
Melhorias na memória do SqlClient #34134
Como o título indica, a alteração 34134 não é significativa por si só. Mas mostra uma técnica interessante que é útil ao tentar reduzir o consumo de memória de um aplicativo ou a frequência do GC.
Considere este código, que usa uma função anônima:
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
[…]
AsyncHelper.ContinueTask(writeTask, tcs, () => tcs.SetResult(null));
Esse tipo de função anônima é conhecido como "encerramento" porque captura ou "fecha" uma variável local "tcs"
. Para criar um encerramento, o compilador deve criar uma classe oculta que contenha todas as variáveis capturadas. Tanto a função original quanto a função anônima delegada mantêm uma referência a uma instância dessa classe oculta. Para mais detalhes, veja o artigo de Richard Carr intitulado C# Closures.
Para evitar a criação de um fechamento, é possível alterar a função anônima para aceitar um parâmetro de estado. Este parâmetro é então alimentado para a função anônima em uma data posterior. Aqui está um exemplo:
AsyncHelper.ContinueTaskWithState(writeTask, tcs, state: tcs, onSuccess: state => ((TaskCompletionSource<object>)state).SetResult(null));
Se esse padrão parece familiar, é porque ele começou a se tornar popular no .NET na era 4.5 quando o padrão de objeto de estado foi adicionado ao Task.ContinueWith. Também é possível observar o padrão no método GetOrAdd de ConcurrentDictionary.
Existem outras otimizações de desempenho relacionadas à memória no .NET Core 3.0 de maneira similar.
Adicionado caminho de extensão na leitura de data e hora para Netcore #31044
Em termos de desempenho bruto, uma das atualizações mais significativas do .NET nos últimos anos é a introdução do tipo Span <T>. Eliminando a necessidade de buffers e strings temporários ao analisar dados binários e de caracteres, a pressão do GC pode ser drasticamente reduzida. Quando a Microsoft atualizou o mecanismo de busca do Bing para o .NET Core 2.1, houve uma queda de 34% na latência.
Embora em alguns casos o uso de Span <t>
seja tratado internamente, aplicá-lo a dados binários geralmente requer a atualização do código. Para ver um exemplo do uso de Span <T> diretamente, veja o pedido pull 31044.
Adicionado suporte para extensão de recurso UTF8 #30917
O pull request 30917 traz o .NET para o alinhamento com o novo suporte do SQL Server 2019 para UTF8. A principal motivação para esse recurso é a capacidade de adicionar internacionalização a aplicativos legados que atualmente usam caracteres de 8 bits. A ativação desse recurso em uma coluna char ou varChar permite que o texto UTF-8 seja armazenado em vez do usual texto não-Unicode, ao mesmo tempo em que oferece suporte à classificação e à indexação.
Internamente, os aplicativos .NET usam o UTF-16. Portanto, para a maioria dos cenários, ainda se deve usar nChar
e nVarChar
para suas necessidades de Unicode. Esse recurso é principalmente para bancos de dados que usam clientes .NET e legados.
Autenticação do Active Directory do Azure usando o token de acesso #30342
Nathan Davidson explica o contexto deste recurso:
A versão desktop mais recente do .NET Framework 4.6 tem uma propriedade chamada AccessToken na classe SqlConnection (MSDN) que pode ser usada para autenticar em um banco de dados do SQL Azure usando um token de acesso emitido pelo Azure AD. No entanto, essa propriedade não está presente na versão do SqlConnection fornecida no pacote System.Data.SqlClient NuGet, incluindo a última visualização v4.3.0-preview1-24530-04. No caso este é um detalhe importante, o projeto em questão é um projeto de biblioteca direcionado para 'netstandard1.6'.
A falta da propriedade AccessToken dificulta, mas não impossibilita, dar suporte a cenários modernos de autenticação baseada em diretório para o SQL DB do Azure e ao mesmo tempo direcionar o .NET Standard (não tentei usar as opções AAD baseadas em cadeia de conexão, mas por várias razões essas não seriam aplicáveis para o meu projeto). Ainda tenho que encontrar uma alternativa além de definir o framework de destino para 'net46', o que gostaria de evitar, exceto como último recurso.
Implementação do SqlFileStream no Windows # 29879
O SQL Server FileStream permite que o banco de dados transicione arquivos. Enquanto os arquivos são fisicamente armazenados em um servidor de arquivos, o banco de dados garante que eles só possam ser manipulados no contexto de uma consulta SQL. Embora um pouco difícil de usar, isso evita muitos dos problemas que normalmente se encontra ao armazenar grandes quantidades de dados não estruturados em uma tabela.
A implementação do SqlFileStream está disponível apenas para o Windows. Especificamente, quando o cliente e o servidor estão sendo executados em uma máquina Windows. O SQL Server no Linux simplesmente não suporta esse recurso, e se o cliente estiver no Linux, "atualmente não há como abrir um arquivo em SMB e passar os Atributos Estendidos".
Adicionando a propriedade de conexão PoolBlockingPeriod #29697
Ao se usar um pool de conexões, que é ativado por padrão, e ocorre um erro de login, todo o pool fica temporariamente bloqueado para tentar novas conexões por cinco segundos. Se a próxima conexão falhar, o bloqueio ocorre novamente por dez segundos. Isso se repete com o tempo duplicando a cada tentativa até que o período de bloqueio atinja um minuto ou uma conexão bem-sucedida redefina o contador.
Embora seja apropriado para a maioria dos cenários do SQL Server no local, o SQL Azure é muito mais propenso a erros transitórios que são resolvidos automaticamente em poucos segundos. Por esse motivo, o padrão das conexões é não usar o bloqueio com o SQL Azure.
Originalmente adicionada no .NET 4.6.2, a configuração de cadeia de conexão PoolBlockingPeriod permite que altere o comportamento para sempre ou nunca bloquear, independentemente do tipo de banco de dados que está sendo conectado. A alteração 29697 adiciona PoolBlockingPeriod ao .NET Core.