Глобальный по сравнению с Singleton в.NET

Если вы используете SQL Server 2016 или выше, вы можете использовать функцию STRING_SPLIT, чтобы превратить разделенную строку @DateIDs в таблицу, соединить ее с вашей таблицей дат (которую я назвал my_date_table с полями). id и date_value), а затем объединить даты с помощью трюка с участием JSON_VALUE и REPLACE (найдено здесь ):

DROP TABLE IF EXISTS #dates;

SELECT
    CONVERT(VARCHAR(10), my_date_table.date_field, 101) AS date_string
INTO #dates
FROM my_date_table
INNER JOIN (
    SELECT [value]
    FROM STRING_SPLIT(@DateIDs, '|')  
) date_ids
    ON date_ids.[value] = my_date_table.id
;

SET @returnDates = COALESCE(
    JSON_VALUE(
        REPLACE(
            (
                SELECT
                    _ = date_string
                FROM #dates
                FOR JSON PATH
            )
        ,'"},{"_":"',', '),'$[0]._'
    )
, '');

5
задан Sean Bright 2 February 2009 в 17:42
поделиться

6 ответов

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

Идеальное решение состояло бы в том, чтобы иметь Вашу загрузку приложения строка подключения из конфигурации и ввести ее в любые классы, которым нужен он. В зависимости от размера Вашего приложения контейнер МОК как Единица или замок Windsor может помочь, но конечно не является необходимой частью решения.

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

Обновление: Просто для уточнения забудьте весь материал о контейнерах МОК на данный момент, "Введите", просто необычный способ сказать "передачу в в качестве параметра" (или конструктору класса, или через свойство, или безотносительно).

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

Обновление № 2: Я думаю, что существует все еще некоторое недоразумение относительно того, что влечет за собой этот подход.

Это в основном сводится, похож ли Ваш класс доступа к данным:

public class DataAccessClass
{
    public DataAccessClass()
    {
        _connString = SomeStaticThing.GetConnectionString();
    }
}

или

public class DataAccessClass
{
    public DataAccessClass(string connString)
    {
        _connString = connString;
    }
}

Они статьи (и на самом деле, многие статьи в том блоге), детализируют много причин, почему последний лучше, чем первый (не в последнюю очередь, потому что первый почти невозможен к модульному тесту).

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

8
ответ дан 18 December 2019 в 07:57
поделиться

Если бы все, что Вы храните, является строкой (возможно наряду с набором других глобальных параметров настройки приложения), я просто использовал бы статический класс с набором свойств для содержания всего это. Одиночный элемент является большим количеством кода и работ по техническому обслуживанию, но это - ненужная работа в этом случае, так как Ваш класс свойств не собирается ДЕЛАТЬ что-либо; просто держите вещи.

4
ответ дан 18 December 2019 в 07:57
поделиться

хорошо видеть столько интеллектуальных решений такой простой проблемы ;-)

существенные факты, от вопроса OP:

  1. строка подключения передается командной строке
  2. много других компонентов, возможно, должны использовать строку подключения

таким образом нет никакого пути вокруг использования статического элемента; является ли это глобальной переменной (трудно, чтобы сделать в.NET, действительно, без класса включения), статического класса, или одиночный элемент действительно не имеет значения. Решением кратчайшего пути был бы статический класс, инициализированный классом Программы, который обработал командную строку.

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

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

5
ответ дан 18 December 2019 в 07:57
поделиться

Это зависит.

Следует иметь в виду что одиночный элемент:

  • осуществляет это точно, один экземпляр класса будет существовать, и
  • обеспечивает глобальный доступ

Глобальное только обеспечивает глобальный доступ, но не делает гарантий о количестве инстанцирований.

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

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

Существует очень немного случаев, где необходимо гарантировать, что точно один экземпляр будет существовать. Поэтому глобальным может быть лучший выбор, чем одиночный элемент.

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

Но часто, может быть предпочтительно иметь его как локальную переменную, которую Вы раздаете к компонентам, которым нужен он. Это может быть сделано вручную, просто передав его конструктору объекта, которому нужен доступ DB, или это может в некоторой степени быть автоматизировано с контейнером МОК.

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

Это также становится более твердым к модульному тесту, снова потому что код даже не скомпилирует, если некоторые внешние данные не будут существовать, который мы идеально хотели бы упустить из нашего теста.

1
ответ дан 18 December 2019 в 07:57
поделиться

как @Anton сказал, у Вас должен быть интерфейс, который выставляет что-то как

interface IConfigurationService
    string ConnectionString

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

Даже при том, что это могло бы казаться большой работой по сравнению с одиночным элементом или глобальный, это понизит связь в Вашем коде, следовательно улучшающем возможность многократного использования, и сделает поблочное тестирование легче, и довольно просто, после того как Вы убеждаете себя, что globals являются (главным образом) злыми :)

Как упомянуто прежде, существует контейнер МОК, который будет служить основой, чтобы сделать это, но это могло бы быть излишество в Вашем случае плюс его хорошее для использования шаблона для себя прежде, чем позволить работе к "волшебному полю"

0
ответ дан 18 December 2019 в 07:57
поделиться

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

Что касается уровня служб, Вам нужен некоторый Сервис Конфигурации, который будет модулем, который части Вашего приложения запросят для конфигурационной информации - строки подключения, URIs, и т.д.:

interface IConfigurationService
    string ConnectionString
    bool IntegratedSecurity
    bool EncryptProfiles

Это должно быть довольно просто, что существует только один экземпляр IConfigurationService в Вашей системе, но это достигается с предпочтительным контейнером DI, не с Шаблоном "одиночка".

Затем, все Ваши сервисы DAL получат ссылку на IConfigurationService:

class FooDal : IFooDal
    IConfigurationService ConfigurationService

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

2
ответ дан 18 December 2019 в 07:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: