Saltar al contenido

¿Cómo leer una cadena de conexión CON PROVIDER en .NET Core?

Te sugerimos que pruebes esta resolución en un entorno controlado antes de enviarlo a producción, saludos.

Solución:

Básicamente estuvo allí, todo lo que tiene que hacer es crear algunas clases fuertemente tipadas para que coincidan con el antiguo ConnectionStringSettings y utilizar alguna lógica de serialización de colección.

Así es como sugeriría formatearlos en json. Algo similar a cómo especificaría una conexión string la antigua forma XML app / web.config. El nombre de la conexión string siendo el key.


  "ConnectionStrings": 
    "Test1": 
      "ConnectionString": "server=localhost;database=db;username=user;password=pass;",
      "ProviderName": "MySql.Data.MySqlClient"
    ,
    "Test2": 
      "ConnectionString": "server=localhost;database=db2;username=user2;password=pass2;",
      "ProviderName": "MySql.Data.MySqlClient"
    
  

Ahora para las clases a las que enlazar. Primero está la clase ConnectionStringSettings simple en sí misma, implementa sus métodos básicos de igualdad / hash (será necesario ya que pretendemos pegar esto en un diccionario).

public class ConnectionStringSettings

    public String Name  get; set; 
    public String ConnectionString  get; set; 
    public String ProviderName  get; set; 

    public ConnectionStringSettings()
    
    

    public ConnectionStringSettings(String name, String connectionString)
        : this(name, connectionString, null)
    
    

    public ConnectionStringSettings(String name, String connectionString, String providerName)
    
        this.Name = name;
        this.ConnectionString = connectionString;
        this.ProviderName = providerName;
    

    protected bool Equals(ConnectionStringSettings other)
    
        return String.Equals(Name, other.Name) && String.Equals(ConnectionString, other.ConnectionString) && String.Equals(ProviderName, other.ProviderName);
    

    public override bool Equals(Object obj)
    
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((ConnectionStringSettings) obj);
    

    public override int GetHashCode()
    
        unchecked
        
            int hashCode = (Name != null ? Name.GetHashCode() : 0);
            hashCode = (hashCode * 397) ^ (ConnectionString != null ? ConnectionString.GetHashCode() : 0);
            hashCode = (hashCode * 397) ^ (ProviderName != null ? ProviderName.GetHashCode() : 0);
            return hashCode;
        
    

    public static bool operator ==(ConnectionStringSettings left, ConnectionStringSettings right)
    
        return Equals(left, right);
    

    public static bool operator !=(ConnectionStringSettings left, ConnectionStringSettings right)
    
        return !Equals(left, right);
    

La siguiente es la colección de ConnectionStringSettings. Esto solo es necesario porque el nombre de la conexión string es el key en la notación JSON. Para mantener ese nombre adjunto de manera consistente, necesitamos anular el método Add de Dictionary (pero no puede hacerlo porque no es virtual). Así que todo lo que REALMENTE estamos haciendo es simplemente ajustar un diccionario internamente con ese bit extra en nuestra propia implementación Add. Nuevamente, esto parece mucho código, pero verá que es algo muy monótono y aburrido.

public class ConnectionStringSettingsCollection : IDictionary

    private readonly Dictionary m_ConnectionStrings;

    public ConnectionStringSettingsCollection()
    
        m_ConnectionStrings = new Dictionary();
    

    public ConnectionStringSettingsCollection(int capacity)
    
        m_ConnectionStrings = new Dictionary(capacity);
    

    #region IEnumerable methods
    IEnumerator IEnumerable.GetEnumerator()
    
        return ((IEnumerable)m_ConnectionStrings).GetEnumerator();
    
    #endregion

    #region IEnumerable<> methods
    IEnumerator> IEnumerable>.GetEnumerator()
    
        return ((IEnumerable>)m_ConnectionStrings).GetEnumerator();
    
    #endregion

    #region ICollection<> methods
    void ICollection>.Add(KeyValuePair item)
    
        ((ICollection>)m_ConnectionStrings).Add(item);
    

    void ICollection>.Clear()
    
        ((ICollection>)m_ConnectionStrings).Clear();
    

    Boolean ICollection>.Contains(KeyValuePair item)
    
        return ((ICollection>)m_ConnectionStrings).Contains(item);
    

    void ICollection>.CopyTo(KeyValuePair[] array, Int32 arrayIndex)
    
        ((ICollection>)m_ConnectionStrings).CopyTo(array, arrayIndex);
    

    Boolean ICollection>.Remove(KeyValuePair item)
    
        return ((ICollection>)m_ConnectionStrings).Remove(item);
    

    public Int32 Count => ((ICollection>)m_ConnectionStrings).Count;
    public Boolean IsReadOnly => ((ICollection>)m_ConnectionStrings).IsReadOnly;
    #endregion

    #region IDictionary<> methods
    public void Add(String key, ConnectionStringSettings value)
    
        // NOTE only slight modification, we add back in the Name of connectionString here (since it is the key)
        value.Name = key;
        m_ConnectionStrings.Add(key, value);
    

    public Boolean ContainsKey(String key)
    
        return m_ConnectionStrings.ContainsKey(key);
    

    public Boolean Remove(String key)
    
        return m_ConnectionStrings.Remove(key);
    

    public Boolean TryGetValue(String key, out ConnectionStringSettings value)
    
        return m_ConnectionStrings.TryGetValue(key, out value);
    

    public ConnectionStringSettings this[String key]
    
        get => m_ConnectionStrings[key];
        set => Add(key, value);
    

    public ICollection Keys => m_ConnectionStrings.Keys;
    public ICollection Values => m_ConnectionStrings.Values;
    #endregion

Algunos métodos de extensión simples para simplificar las cosas.

public static class ConnectionStringSettingsExtensions

    public static ConnectionStringSettingsCollection ConnectionStrings(this IConfigurationRoot configuration, String section = "ConnectionStrings")
    
        var connectionStringCollection = configuration.GetSection(section).Get();
        if (connectionStringCollection == null)
        
            return new ConnectionStringSettingsCollection();
        

        return connectionStringCollection;
    

    public static ConnectionStringSettings ConnectionString(this IConfigurationRoot configuration, String name, String section = "ConnectionStrings")
    
            !connectionStringCollection.TryGetValue(name, out connectionStringSettings))
        
            return null;
        

        return connectionStringSettings;
    

Finalmente el uso.

var configuration = new ConfigurationBuilder()
    .AddJsonFile("config.json")
    .Build();

var connectionStrings = configuration.ConnectionStrings();

foreach (var connectionString in connectionStrings.Values)

    Console.WriteLine(connectionString.Name);
    Console.WriteLine(connectionString.ConnectionString);
    Console.WriteLine(connectionString.ProviderName);


var specificConnStr1 = connectionStrings["Test1"];
Console.WriteLine(specificConnStr1.Name);
Console.WriteLine(specificConnStr1.ConnectionString);
Console.WriteLine(specificConnStr1.ProviderName);

var specificConnStr2 = configuration.ConnectionString("Test2");
Console.WriteLine(specificConnStr2.Name);
Console.WriteLine(specificConnStr2.ConnectionString);
Console.WriteLine(specificConnStr2.ProviderName);

Una vieja pregunta, pero estaba viendo este tema hoy y pensé en compartir …

Una alternativa simple para incluir ProviderName

Aquí hay una alternativa simple que evita las extensiones personalizadas y la alteración de la estructura de configuración de ConnectionStrings predeterminada. Se basa en cómo Microsoft incluye un ProviderName para aplicaciones en Azure.

La solución es agregar un contexto relacionado key en la sección ConnectionStrings que especifica el ProviderName.

AppSettings.json con el proveedor de SQLite:

  
  "ConnectionStrings": 
    "MyContext": "Data Source=c:\MySqlite.db;Version=3;",
    "MyContext_ProviderName": "System.Data.SQLite",
  

Y en el código C # lea los valores con el método GetConnectionString ():

var connectionString = Configuration.GetConnectionString("MyContext");
var providerName = Configuration.GetConnectionString("MyContext_ProviderName") ?? "";

if (Regex.IsMatch(providerName, "SQLite", RegexOptions.IgnoreCase)) 

    builder.UseSqlite(connectionString);

else if (Regex.IsMatch(providerName, "Oracle", RegexOptions.IgnoreCase)) 
    
    builder.AddOracle(connectionString);

else if (... 

Bono – Prefijos de cadena de conexión

Microsoft incluye prefijos predefinidos para SQLClient y MySQL que incluirán automáticamente el nombre del proveedor en el formato anterior. Sin embargo, estos prefijos solo funcionan cuando se agregan como variables de entorno, es decir, no en appsettings.json. Por ejemplo, definir la conexión string en launchSettings.json con el MYSQLCONNSTR_ prefix poblaría tanto la conexión string y nombre del proveedor. Para detenciones, consulte Configuración en ASP.NET Core y desplácese hacia abajo para Conexión string prefijos

launchSettings.json

{
  "profiles": 
    "Development": 
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "",
      "environmentVariables": 
       "ASPNETCORE_ENVIRONMENT": "Development",

       // The prefix
       "MYSQLCONNSTR_MyContext": "Server=myServerAddress;Database=Green;Uid=myUsername;Pwd=myPassword;"

      
    

Si posees alguna desconfianza o disposición de arreglar nuestro enunciado eres capaz de escribir un paráfrasis y con gusto lo ojearemos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *