Подтвердить что ты не робот

Присоединение ада в .NET/LINQ-SQL/ASP.NET

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

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

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

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

Как мне лучше разрешить этот беспорядок?

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

4b9b3361

Ответ 1

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

Если это не сработает для вас, вы можете указать строку подключения в конструкторе контекста данных. В вашем веб-проекте есть статический класс, который загружает ваши настройки, включая строки подключения, и когда вы создаете свой объект 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))
{
   ...
}

Ответ 2

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

Ответ 3

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

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

Pro:

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

Con:

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

Ответ 4

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

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

_connectionString = ConfigurationManager.AppSettings["ConnectionString"];

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

Ответ 5

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

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

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

Ответ 6

У меня тоже была битва с этой проблемой. Я нашел решение, используя определение частичного класса С# и расширив datacontext, созданный разработчиком dbml. Это решение вполне похоже на ответ tvanfosson. Вам нужно создать частичный класс datacontext со стандартным конструктором, который получает ConnectionString из настроек, а в свойствах DC DC-конструктора dbml устанавливается соединение с None. Таким образом, строка соединения не будет скомпилирована в dll. Datacontext автоматически получит строку подключения из настроек web.config connectionstring. Я не проверял, работает ли это с 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();
        }
    }
}

Ответ 7

Чтобы защитить его от чего-либо в автоматическом сгенерированном коде, переопределите информацию о соединении в методе 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 может использовать свой путь (что не очень хорошо за пределами веб-проекта), но вы получаете окончательный контроль над соединением при запуске приложения.

Ответ 8

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

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

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

Ответ 9

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

Ответ 10

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

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

Ответ 11

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

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

Ответ 12

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

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

Pro:

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

Con:

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

Ответ 13

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

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

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

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

Обратите внимание: если вы разместили класс контекста пользовательских данных в той же сборке, просто включите имя класса, например. CustomDataContext.

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

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

Что это.

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

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

НТН