Domanda

Ho un'applicazione web che comprende quanto segue:

  • Un progetto Web (con un file web.config contenente una stringa di connessione, ma nessun codice di accesso ai dati nel progetto Web)
  • Un progetto di accesso ai dati che utilizza le classi LINQ-SQL per fornire entità all'interfaccia utente del progetto Web (questo progetto ha un file di impostazioni e un'app.config - entrambi con stringhe di connessione)

Quando eseguo la compilazione e la distribuzione, non esiste alcun file di impostazioni o app.config nella directory Bin con l'accesso ai dati .dll, ma la modifica della stringa di connessione nel file web.config non modifica il database di conseguenza, quindi il la stringa di connessione deve essere compilata nella dll di accesso ai dati.

Ciò di cui ho bisogno è un file di configurazione per la mia intera distribuzione - sito Web, dll di accesso ai dati, tutto - che abbia una stringa di connessione che viene utilizzata. Al momento sembrano esserci più stringhe di connessione che vengono utilizzate o codificate ovunque.

Come posso risolvere al meglio questo casino?

Grazie per l'aiuto.

È stato utile?

Soluzione

Non ho mai avuto problemi con il Data Access Layer (DAL) in grado di usare le stringhe di connessione dal mio file web.config . Di solito copio semplicemente la sezione delle stringhe di connessione dal DAL e la incollo nel web.config . Sto usando il designer DBML per creare il contesto dei dati.

Se questo non funziona per te, puoi specificare la stringa di connessione nel costruttore del contesto dati. Nel tuo progetto web hai una classe statica che carica le tue impostazioni, comprese le stringhe di connessione, e quando crei il tuo oggetto DAL (o il contesto dei dati, se lo crei direttamente), passalo al costruttore.

public static class GlobalSettings
{
    private static string dalConnectionString;
    public static string DALConnectionString
    {
       get
       {
           if (dalConnectionString == null)
           {
              dalConnectionString = WebConfigurationManager
                                      .ConnectionStrings["DALConnectionString"]
                                        .ConnectionString;
           }
           return dalConnectionString;
       }
    }
}
...

using (var context = new DALDataContext(GlobalSettings.DALConnectionString))
{
   ...
}

Altri suggerimenti

Il file di configurazione per il progetto di avvio definirà le impostazioni di configurazione per tutti i progetti inclusi. Ad esempio, se il tuo progetto web è il progetto di avvio, qualsiasi riferimento a " appSettings " cercherà le impostazioni da web.config, questo include tutti i riferimenti a " appSettings " dal tuo progetto di accesso ai dati. Quindi copia tutte le impostazioni di configurazione dall'app.config del progetto di accesso ai dati nel web.config del progetto web.

Installa la tua ConnectionFactory in base al registro:

  • aggiungi una chiave di registro per la tua applicazione sotto SOFTWARE / [YOUR_COMPANY] / [YOUR_APP]
  • aggiungi un valore stringa per ConnectionString
  • Insegna a ConnectionFactory a aprire la chiave di registro appropriata (in un costruttore statico, non a ogni caricamento di pagina!).
  • esporta le informazioni del Registro di sistema come file .reg, aggiungile al controllo del codice sorgente, modificale e applicale se necessario per configurare macchine aggiuntive.

Pro:

  • Semplice da configurare
  • Connectionstring vive in un unico posto
  • Non in web / app.config, quindi non è necessario codificare le impostazioni specifiche dell'ambiente.
  • Non in web / app.config, quindi Junior Dev Jimmy non può dire accidentalmente al server di produzione di guardare il database DEV

Con:

  • Non immediatamente ovvio che cose importanti vivono nel registro, quindi i nuovi sviluppatori avranno bisogno di istruzioni.
  • Passaggio aggiuntivo durante la configurazione di una nuova macchina di distribuzione
  • Il registro è oldskool. Gli sviluppatori junior ti derideranno.

Grazie per le risposte.

Quelli di voi che affermano che l'app utilizzerà l'impostazione in web.config sono corretti per i casi in cui faccio riferimento nel mio codice:

_connectionString = ConfigurationManager.AppSettings["ConnectionString"];

..ma c'è un problema diverso con i datacontex LINQ-SQL: penso che includano stringhe di connessione nella dll compilata per l'uso nel costruttore senza parametri. Come dice tvanofosson, ho bisogno di creare contesti dati passando un riferimento alla stringa di connessione in web.config. È qui che mi sono imbrogliato :)

Ho anche avuto un po 'di fatica con questo problema. Ho trovato una soluzione usando la definizione di classe parziale c # ed estendendo il datacontext creato dal designer dbml. Questa soluzione è abbastanza simile alla risposta di tvanfosson. Quello che devi fare è creare una classe datacontext parziale con il costruttore predefinito che ottiene ConnectionString dalle impostazioni e nelle proprietà DC del designer dbml imposta la connessione su Nessuno. In questo modo la stringa di connessione non sarà compilata in dll. Datacontext otterrà automaticamente la stringa di connessione dalle impostazioni di connectiontring web.config. Non ho testato se funziona anche con app.config, ma penso che dovrebbe funzionare bene.

Ecco un esempio di classe DC parziale:

namespace MyApplication {
    /// <summary>
    /// Summary description for MyDataContext
    /// </summary>
    /// 
    public partial class MyDataContext
    {
        public MyDataContext() :
            base(global::System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString, mappingSource)
        {
            OnCreated();
        }
    }
}

L'applicazione utilizzerà solo le voci di configurazione nel file web.config. È possibile inserire le impostazioni di configurazione DLL nel file web.config purché siano strutturate correttamente. Il mio esempio è specifico di VB usando My Namespace, ma ti dà l'idea generale.

Nella paret configSections del file di configurazione è necessario inserire una voce:

<configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
        <section name="YourAssembly.My.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup></configSections>

Quindi nella parte applicationSettings del file di configurazione inserisci le voci per ogni dll:

    <applicationSettings>
      <YourAssembly.My.MySettings>
        <setting name="DebugMode" serializeAs="String">
            <value>False</value>
        </setting>
      </YourAssembly.My.MySettings>
    </applicationSettings>  

Per proteggerlo da qualsiasi cosa nel codice generato automaticamente, sovrascrivi le informazioni di connessione nel metodo OnCreated () del contesto dei dati:

using System.Configuration;
namespace MyApplication 
{
    partial void OnCreated()
    {
        // attempt to use named connection string from the calling config file
        var conn = ConfigurationManager.ConnectionStrings["MyConnectionString"];
        if (conn != null) Connection.ConnectionString = conn.ConnectionString;
    }
}

In questo modo il designer di dbml può fare cose di connessione a modo suo (che non è carino al di fuori di un progetto web), ma ottieni il controllo finale della connessione quando l'applicazione viene eseguita.

Ecco un modo per vederlo. Quale componente dovrebbe prendere la decisione su quale database utilizzare? È possibile che il database (o almeno la stringa di connessione) possa cambiare in futuro. Il sito Web decide quale database utilizzare? Oppure, il DAL decide?

Se si dispone di database di sviluppo, controllo qualità, UAT e prod, la gestione di queste stringhe di connessione è fondamentale.

Se il sito web decide, dovrebbe passare la stringa di connessione dal suo web.config al DAL. Se il sito Web non deve sapere o preoccuparsi della provenienza dei dati, la stringa di connessione appartiene al DAL.

Che ne dici di definire un oggetto ConnectionFactory, che accetta un enum come parametro e restituisce un oggetto di connessione completamente formato?

È inoltre possibile che l'applicazione Web fornisca la stringa di connessione quando è necessario utilizzare il progetto di accesso ai dati. Potresti renderlo parte del costruttore.

Inoltre, potresti semplicemente scrivere la tua logica per caricare una stringa di connessione da un file esterno quando il progetto di accesso ai dati effettua le chiamate.

In un mondo perfetto, penso che rifaresti il ??tuo livello dati per raccogliere le impostazioni di configurazione tramite System.Configuration o costruttori / fabbriche pertinenti. Ciò significa che è necessario ricollegare l'origine di configurazione implicita o impostare esplicitamente le connessioni dal suo host / consumatore. Un altro modello correlato per centralizzare questi tipi di costanti è quello di lanciare una proprietà di sola lettura in una classe di supporto statica e far sì che quella classe gestisca la risoluzione effettiva da configurazioni, ecc.

Un posto in cui puoi vedere che penso mostri buoni esempi di come farlo elegantemente è NHibernate e la sua gestione di configurazione / mappature. Certo, è un po 'un inferno di xml e Fluent NHib è più zuccherino, ma la maggior parte dei campioni del mondo reale ti mostrerà come riconciliare la configurazione da un assembly di supporto con l'assembly in esecuzione.

Installa la tua ConnectionFactory in base ai file .config:

  • Definisci una sezione di configurazione personalizzata per mappare le coppie chiave / connessioni
  • Insegna a ConnectionFactory ad annusare quella sezione di configurazione usando hostname o machinename come appropriato
  • Popolare i valori chiave / connectionstring per i vari server dev / qa / prod e rilasciali nei vari file app.config, web.config ecc.

Pro:

  • Tutte le vite all'interno del progetto, quindi nessuna sorpresa
  • L'aggiunta di una destinazione di distribuzione aggiuntiva è un'operazione copia / incolla in un file .config

Con:

  • Crea grandi e brutte sezioni XML, specialmente se hai una dozzina di server di produzione
  • Deve essere duplicato tra progetti
  • Richiede la modifica del codice & amp; ridistribuire per aggiungere un nuovo obiettivo
  • Il codice deve conoscere l'ambiente in cui vivrà

So che questo è vecchio ma ecco come lo faccio (mi piace molto alla maniera di @ Seba ma non l'ho provato)

Ciò presuppone che il file DBML risieda nella propria libreria di classi, che ho trovato più conveniente quando si condividono entità e accesso ai dati su più siti Web e altre librerie di classi. Presuppone anche che tu abbia nominato la stringa di connessione uguale in ogni progetto. Uso NAnt per impostarlo quando eseguo la distribuzione in ambienti diversi.

Ho basato questo sulla risposta più sopra di @tvanfosson - complimenti a quel ragazzo.

  1. Crea la tua classe base, che deriva da LinqDataContext

Ecco il codice VB:

    Imports System.Configuration

Public Class CustomDataContextBase
    Inherits System.Data.Linq.DataContext
    Implements IDisposable

    Private Shared overrideConnectionString As String

    Public Shared ReadOnly Property CustomConnectionString As String
        Get
            If String.IsNullOrEmpty(overrideConnectionString) Then
                overrideConnectionString = ConfigurationManager.ConnectionStrings("MyAppConnectionString").ConnectionString
            End If

            Return overrideConnectionString
        End Get
    End Property

    Public Sub New()
        MyBase.New(CustomConnectionString)
    End Sub

    Public Sub New(ByVal connectionString As String)
        MyBase.New(CustomConnectionString)
    End Sub

    Public Sub New(ByVal connectionString As String, ByVal mappingSource As System.Data.Linq.Mapping.MappingSource)
        MyBase.New(CustomConnectionString, mappingSource)
    End Sub

    Public Sub New(ByVal connection As IDbConnection, ByVal mappingSource As System.Data.Linq.Mapping.MappingSource)
        MyBase.New(CustomConnectionString, mappingSource)
    End Sub

End Class
  1. Apri il tuo file DBML e, nelle Proprietà, aggiungi il nome della classe sopra alla proprietà Classe di base.

Nota, se hai inserito la classe di contesto dei dati personalizzati nello stesso assembly, includi semplicemente il nome della classe, ad es. CustomDataContext.

Se si trovano in assiemi diversi, utilizzare il nome completo, ad es. MyCo.MyApp.Data.CustomDataContext

  1. Per assicurarsi che le cose di Designer funzionino correttamente, copiare la stringa di connessione nel file app.config per la libreria di classi. Questo non verrà utilizzato a parte nell'IDE.

Questo è tutto.

Dovrai assegnare lo stesso nome alla tua stringa di connessione

Quello che stai essenzialmente facendo è forzare il contesto dei dati a ignorare le informazioni di connessione impostate nel file DBML. L'uso dei metodi ConfigurationManager significherà che raccoglierà la stringa di connessione dall'assembly chiamante.

HTH

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top