Вопрос

У меня есть веб-приложение, которое включает в себя следующее:

  • Веб-проект (с файлом web.config, содержащим строку подключения, но без кода доступа к данным в веб-проекте)
  • Проект доступа к данным, который использует классы LINQ-SQL для предоставления объектов пользовательскому интерфейсу веб-проекта (у этого проекта есть файл настроек и app.config - оба из которых имеют строки подключения)

Когда я создаю и развертываю, в каталоге Bin с библиотекой data access .dll нет файла настроек или app.config, но изменение строки подключения в файле web.config соответствующим образом не изменяет базу данных, поэтому строка подключения должна быть скомпилирована в библиотеку data access dll.

Что мне нужно, так это один конфигурационный файл для всего моего развертывания - веб-сайт, библиотеки DLL для доступа к данным, все, - который имеет одну строку подключения, которая используется.На данный момент, похоже, повсюду используется или жестко закодировано несколько строк подключения.

Как мне лучше всего разрешить эту неразбериху?

Спасибо за любую помощь.

Это было полезно?

Решение

У меня никогда не было проблем с Уровень доступа к данным (DAL) возможность использовать строки подключения из моего web.config файл.Обычно я просто копирую раздел строки подключения из DAL и вставляю его в web.config.Я использую DBML designer для создания контекста данных.

Если у вас это не сработает, вы можете указать строку подключения в конструкторе контекста данных.В вашем веб-проекте есть статический класс, который загружает ваши настройки, включая строки подключения, и когда вы создаете свой объект DAL (или контекст данных, если создаете его напрямую), просто передайте его конструктору.

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))
{
   ...
}

Другие советы

Файл конфигурации для проекта startup будет определять параметры конфигурации для всех включенных проектов.Например, если ваш веб-проект является проектом запуска, любая ссылка на "AppSettings" будет искать настройки из web.config, сюда входят любые ссылки на "AppSettings" из вашего проекта доступа к данным.Поэтому скопируйте все настройки конфигурации из app.config проекта доступа к данным в web.config веб-проекта.

Создайте свой собственный ConnectionFactory на основе реестра:

  • добавьте раздел реестра для вашего приложения в разделе ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ/[YOUR_COMPANY]/[YOUR_APP]
  • добавьте строковое значение для ConnectionString
  • Научите ваш ConnectionFactory взламывать соответствующий раздел реестра (в статическом конструкторе, а не при загрузке каждой страницы!).
  • экспортируйте информацию реестра в виде reg-файла, добавьте его в систему управления версиями, измените и примените по мере необходимости для настройки дополнительных компьютеров.

Профессиональный:

  • Простая настройка
  • Connectionstring живет в одном месте
  • Отсутствует в web /app.config, поэтому нет необходимости жестко кодировать настройки, зависящие от среды.
  • Не в web /app.config, поэтому младший разработчик Джимми не сможет случайно указать вашему производственному серверу просмотреть базу данных разработчиков

Con:

  • Не сразу очевидно, что важные вещи хранятся в реестре, поэтому новым разработчикам понадобятся инструкции.
  • Дополнительный шаг при настройке новой машины развертывания
  • Реестр - это олдскул.Младшие разработчики будут издеваться над вами.

Спасибо за ответы.

Те из вас, кто говорит, что приложение будет использовать настройку в web.config, правы для случаев, когда я ссылаюсь на нее в своем собственном коде:

_connectionString = ConfigurationManager.AppSettings["ConnectionString"];

..но есть другая проблема с LINQ-SQL datacontexts - я думаю, что они включают строки connections в скомпилированную dll для использования в конструкторе без параметров.Как говорит tvanofosson, мне нужно создать datacontexts, передав ссылку на строку подключения в web.config.Вот тут-то я и запутался :)

У меня тоже была небольшая проблема с этим вопросом.Я нашел решение, используя определение частичного класса c # и расширяя datacontext, созданный dbml designer.Это решение вполне похоже на ответ тванфоссона.Что вам нужно сделать, это создать частичный класс datacontext с конструктором по умолчанию, получающим ConnectionString из настроек, и в свойствах dbml designer DC установить connection в None.Таким образом, строка подключения не будет скомпилирована в dll.Datacontext автоматически получит строку подключения из настроек connectionstring web.config.Я не проверял, работает ли это также с app.config, но я думаю, что это должно работать нормально.

Вот пример частичного класса DC:

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

Ваше приложение будет использовать только записи конфигурации в файле web.config.Вы можете поместить настройки конфигурации dll в файл web.config, если они правильно структурированы.Мой пример специфичен для VB с использованием пространства имен My, но он дает вам общее представление.

В разделе configSections paret конфигурационного файла вам понадобится запись:

<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>

Затем в часть ApplicationSettings конфигурационного файла вы помещаете записи для каждой библиотеки dll:

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

Чтобы защитить его от чего-либо в автоматически сгенерированном коде, переопределите информацию о соединении в методе onCreated() контекста данных:

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;
    }
}

Таким образом, разработчик dbml может создавать соединения по-своему (что не очень хорошо за пределами веб-проекта), но вы получаете окончательный контроль над соединением при запуске приложения.

Вот один из способов взглянуть на это.Какой компонент должен принимать решение о том, какую базу данных использовать?Вполне возможно, что база данных (или, по крайней мере, строка подключения) может измениться в будущем.Решает ли веб-сайт, какую базу данных использовать?Или это решает DAL?

Если у вас есть базы данных dev, QA, UAT и prod, управление этими строками подключения имеет решающее значение.

Если веб-сайт примет решение, он должен передать строку подключения из своего web.config в DAL.Если предполагается, что веб-сайт не должен знать или заботиться о том, откуда поступают данные, тогда строка подключения принадлежит DAL.

Как насчет определения объекта ConnectionFactory, который принимает перечисление в качестве параметра и возвращает полностью сформированный объект connection?

Вы также могли бы попросить веб-приложение предоставить строку подключения, когда ему необходимо использовать проект доступа к данным.Вы могли бы сделать это частью конструктора.

Кроме того, вы могли бы просто написать свою собственную логику для загрузки строки подключения из внешнего файла, когда проект доступа к данным выполняет свои вызовы.

В идеальном мире, я думаю, вы бы реорганизовали свой уровень данных, чтобы подобрать параметры конфигурации через System.Конфигурация или соответствующие конструкторы / фабрики.Это означает, что вам либо нужно перепрограммировать его неявный источник конфигурации, либо явно установить соединения с его хостом / потребителем.Другой связанный шаблон для централизации этих типов констант заключается в том, чтобы добавить свойство, доступное только для чтения, в статический вспомогательный класс и заставить этот класс управлять фактическим разрешением из конфигураций и т.д.

Единственное место, куда вы можете заглянуть, которое, я думаю, показывает хорошие примеры того, как сделать это элегантно, - это NHibernate и его управление конфигурацией / сопоставлениями.Конечно, это немного похоже на xml-ад, а Fluent NHib более слащав, но большинство примеров из реального мира покажут вам, как согласовать конфигурацию из поддерживающей сборки сисполняющая сборка.

Создайте свой собственный ConnectionFactory на основе файлов .config:

  • Определите пользовательский раздел конфигурации для сопоставления пар ключ / строка подключения
  • Научите ваш ConnectionFactory просматривать этот раздел конфигурации, используя имя хоста или machinename в зависимости от обстоятельств
  • Заполните значения key / connectionstring для ваших различных серверов dev / qa / prod и поместите их в различные ваши app.config, web.config и т.д.Файлы.

Профессиональный:

  • Все живет внутри проекта, так что никаких сюрпризов
  • Добавление дополнительной цели развертывания - это операция копирования / вставки в файл .config

Con:

  • Создает большие уродливые XML-разделы, особенно если у вас есть дюжина производственных серверов
  • Необходимо дублировать между проектами
  • Требуется изменение кода и повторное развертывание для добавления новой цели
  • Код должен знать об окружающей среде, в которой он будет жить

Я знаю, что это устарело, но вот как я это делаю (мне очень нравится способ @Seba, но я этого не пробовал)

Это предполагает, что ваш файл DBML находится в его собственной библиотеке классов, что, на мой взгляд, наиболее удобно при совместном использовании объектов и доступе к данным на нескольких веб-сайтах и в других библиотеках классов.Это также предполагает, что вы назвали свою строку подключения одинаково в каждом проекте.Я использую NAnt, чтобы установить это при развертывании в разных средах.

Я основал это на главном ответе выше от @tvanfosson - слава этому парню.

  1. Создайте свой собственный базовый класс, который является производным от LinqDataContext

Вот код 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. Откройте ваш файл DBML и в Свойствах добавьте указанное выше имя класса к свойству базового класса.

Обратите внимание, если вы разместили пользовательский класс контекста данных в той же сборке, просто укажите имя класса, напримерПользовательский DataContext.

Если они находятся в разных сборках, используйте полное имя, напримерMyCo.MyApp.Data.CustomDataContext.MyCo.MyApp.Данные.Пользовательский DataContext

  1. Чтобы убедиться, что содержимое конструктора работает должным образом, скопируйте строку подключения в файл app.config для библиотеки классов.Это не будет использоваться отдельно от IDE.

Вот и все.

Вам нужно будет назвать вашу строку подключения таким же образом

По сути, вы заставляете контекст данных игнорировать информацию о соединении, установленную в файле DBML.Использование методов ConfigurationManager будет означать, что он получит строку подключения из вызывающей сборки.

HTH

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top