Entity Framework 6 Fornecedor SQL Server baseado em Microsoft.Data.SqlClient

Este fornecedor do Entity Framework 6 é um fornecedor de substituição do fornecedor SQL Server incorporado.

Este fornecedor depende do atual fornecedor de ADO.NET Microsoft.Data.SqlClient , que inclui as seguintes vantagens em relação ao driver atualmente utilizado:

  • Cliente atual recebe suporte total, em contraste com System.Data.SqlClient, que está em modo de manutenção.
  • Suporta novas funcionalidades do SQL Server, incluindo suporte para o SQL Server 2022 enhanced client protocol (TDS8)
  • Suporta a maioria dos métodos de autenticação do Azure Active Directory
  • Suporta sempre encriptação com .NET

Note que este fornecedor é apenas uma atualização em tempo de execução e não funcionará com as ferramentas existentes do Visual Studio.

A versão mais recente deste pacote está disponível na NuGet

Configuração

Existem várias formas de configurar o Entity Framework para usar este fornecedor.

Pode registar o fornecedor em código usando um atributo:

[DbConfigurationType(typeof(MicrosoftSqlDbConfiguration))]
public class SchoolContext : DbContext
{
    public SchoolContext() : base()
    {
    }

    public DbSet<Student> Students { get; set; }
}

Se tiveres várias classes a herdar do DbContext na tua solução, adiciona o atributo DbConfigurationType a todas elas.

Ou pode usar o método SetConfiguration antes de qualquer chamada de acesso a dados:

 DbConfiguration.SetConfiguration(new MicrosoftSqlDbConfiguration());

Ou adicione as seguintes linhas à sua classe DbConfiguration derivada existente:

SetProviderFactory(MicrosoftSqlProviderServices.ProviderInvariantName, Microsoft.Data.SqlClient.SqlClientFactory.Instance);
SetProviderServices(MicrosoftSqlProviderServices.ProviderInvariantName, MicrosoftSqlProviderServices.Instance);
// Optional
SetExecutionStrategy(MicrosoftSqlProviderServices.ProviderInvariantName, () => new MicrosoftSqlAzureExecutionStrategy());

Também pode usar a configuração baseada em App.Config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />    
    </configSections>
    <entityFramework>
        <providers>
            <provider invariantName="Microsoft.Data.SqlClient" type="System.Data.Entity.SqlServer.MicrosoftSqlProviderServices, Microsoft.EntityFramework.SqlServer" />
        </providers>
    </entityFramework>
    <system.data>
        <DbProviderFactories>
           <add name="SqlClient Data Provider"
             invariant="Microsoft.Data.SqlClient"
             description=".NET Framework Data Provider for SqlServer"
             type="Microsoft.Data.SqlClient.SqlClientFactory, Microsoft.Data.SqlClient" />
        </DbProviderFactories>
    </system.data>
</configuration>

Se usar o App.Config com uma aplicação .NET 6 ou superior, deve remover a secção <system.data> acima e registar o DbProviderFactory no código apenas uma vez.

DbProviderFactories.RegisterFactory(MicrosoftSqlProviderServices.ProviderInvariantName, Microsoft.Data.SqlClient.SqlClientFactory.Instance);

Utilização do EDMX

Se usar um ficheiro EDMX, atualize o Provider nome:

<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
  <edmx:Runtime>
    <edmx:StorageModels>
      <Schema Namespace="ChinookModel.Store" Provider="Microsoft.Data.SqlClient" >

Para usar o ficheiro EDMX com o designer Visual Studio, deve voltar a mudar o nome do fornecedor para System.Data.SqlClient

Também atualize o nome do fornecedor dentro da cadeia de ligação EntityConnection - provider=Microsoft.Data.SqlClient

 <add 
    name="Database" 
    connectionString="metadata=res://*/EFModels.csdl|res://*/EFModels.ssdl|res://*/EFModels.msl;provider=Microsoft.Data.SqlClient;provider connection string=&quot;data source=server;initial catalog=mydb;integrated security=True;persist security info=True;" 
    providerName="System.Data.EntityClient" 
 />

Alterações de código

Para usar o fornecedor numa solução existente, são necessárias algumas alterações ao código (conforme necessário).

using System.Data.SqlClient; =>using Microsoft.Data.SqlClient;

using Microsoft.SqlServer.Server; =>using Microsoft.Data.SqlClient.Server;

As seguintes classes foram renomeadas para evitar conflitos com as classes que usam System.Data.SqlClient no fornecedor existente do SQL Server:

SqlAzureExecutionStrategy =>MicrosoftSqlAzureExecutionStrategy

SqlDbConfiguration =>MicrosoftSqlDbConfiguration

SqlProviderServices =>MicrosoftSqlProviderServices

SqlServerMigrationSqlGenerator =>MicrosoftSqlServerMigrationSqlGenerator

SqlSpatialServices =>MicrosoftSqlSpatialServices

SqlConnectionFactory =>MicrosoftSqlConnectionFactory

LocalDbConnectionFactory =>MicrosoftLocalDbConnectionFactory

Problemas conhecidos

Azure App Service com .NET Framework e configuração de cadeias de conexão

Se usar o Azure App Service com o .NET Framework e a funcionalidade de configuração de strings de ligação, pode encontrar problemas de runtime, pois a ProviderName definição das strings de ligação neste cenário está codificada fixamente para System.Data.SqlClient.

A solução é usar uma classe MicrosoftSqlDbConfiguration derivada assim:

public class AppServiceConfiguration : MicrosoftSqlDbConfiguration
{
    public AppServiceConfiguration()
    {
        SetProviderFactory("System.Data.SqlClient", Microsoft.Data.SqlClient.SqlClientFactory.Instance);
        SetProviderServices("System.Data.SqlClient", MicrosoftSqlProviderServices.Instance);
        SetExecutionStrategy("System.Data.SqlClient", () => new MicrosoftSqlAzureExecutionStrategy());
    }
}

Depois, use esta classe derivada na configuração baseada em código descrita acima.

EntityFramework.dll instalado no GAC

Se uma versão mais antiga do EntityFramework.dll estiver instalada no .NET Framework GAC (Global Assembly Cache), pode aparecer este erro:

The 'PrimitiveTypeKind' attribute is invalid - The value 'HierarchyId' is invalid according to its datatype

A solução é remover o .dll do GAC. Os conjuntos EF6 nunca devem ser instalados no GAC.