Создание класса доступа к данным для всех программ или отдельного C#

Так что название немного расплывчато, но вопрос на самом деле таков: на практике лучше всего создать класс доступа к данным, в данном случае доступ к SQL Server.

Где все статические методы класса нуждаются в строке подключения и операторе SQL?

Что-то в этом роде:

public static void ExecuteSql(string connStr, string strSqlStatement)
{
    SqlConnection conn = new SqlConnection(connStr);
    conn.Open();

    SqlCommand cmd = new SqlCommand(strSqlStatement, conn);
    cmd.ExecuteNonQuery();

    conn.Close();
    conn.Dispose();
}

А затем метод, который делает что-то подобное, но возвращает запрошенные вами данные.

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

 obj.GetSomethingViaQueryThatIsWrittenInTheClassLibrary()

Поэтому я предполагаю, что первый больше похож на сервисную библиотеку для доступа и записи данных в базу данных SQL Server. Что обычно делают в такой ситуации?

Или вы могли бы даже использовать сервисную библиотеку в тандеме с библиотекой объектов?

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


person MZawg    schedule 14.11.2018    source источник
comment
Или, в-третьих, используйте ORM что-то вроде Entity Framework. Что устраняет проблемы со строками подключения / SQL-инъекциями / сенсорными запросами.   -  person Jeroen van Langen    schedule 14.11.2018
comment
Я не уверен, что ваш вопрос достаточно конкретен для переполнения стека, поскольку вам нужен более общий совет по созданию уровня доступа к данным в .Net. Однако я могу дать один совет: вы должны использовать ключевое слово using при открытии соединения с базой данных. stackoverflow.com/ вопросы/5642469/   -  person nick gowdy    schedule 14.11.2018
comment
Посмотрите на шаблон проектирования репозитория, который довольно часто используется. Хорошим примером может служить Entity Framework.   -  person Josef Fazekas    schedule 14.11.2018
comment
@JosefFazekas, так что здесь есть на что посмотреть, но похоже, что доступ к данным обычно является отдельным уровнем приложения?   -  person MZawg    schedule 14.11.2018
comment
@nickgowdy Спасибо :).   -  person MZawg    schedule 14.11.2018
comment
@ J.vanLangen Итак, вы бы выбрали EF через соединение ADO.net, например? Ради удобочитаемости и простоты или программирования?   -  person MZawg    schedule 14.11.2018
comment
@J.vanLangen, такие статьи всегда заставляют меня задуматься, помогаю я организации или вредлю ей: iamtimcorey.com/ask-tim-dont-use-entity-framework , вот откуда некоторые из моих вопросов о стеке.   -  person MZawg    schedule 14.11.2018
comment
Я бы выбрал EF, если я пишу приложение, которое позволяет пользователям взаимодействовать с данными из базы данных. Я бы выбрал ADO.net, если мне нужно обрабатывать большие объемы данных (например, импорт/экспорт)   -  person Jeroen van Langen    schedule 14.11.2018
comment
@MikeCMR Нет правильного или неправильного ответа на вопрос об использовании EF против Dapper. Они оба имеют свои преимущества и недостатки. Изучите оба, а затем выберите в зависимости от потребностей.   -  person mason    schedule 14.11.2018
comment
@MikeCMR Да, но это кроличья нора, в которую можно попасть, добавляя слой за слоем. Мне нравится, чтобы в моих проектах все было просто, и я создаю уровень доступа к данным, обычно содержащий DAL в имени, содержащий репозитории (это будет один или два контекста EF) и мои классы POCO. Конечно, вы можете добавить еще один слой для своих моделей, но, как сказал Мейсон: это дизайнерское решение, которое сильно зависит от масштаба вашего проекта.   -  person Josef Fazekas    schedule 15.11.2018
comment
@JosefFazekas Спасибо! Ваш вклад и советы очень ценятся и очень полезны. Я смотрел на это так, как будто мне нужно написать уровень доступа к данным только один раз и добавить его в любой проект, который у меня когда-либо был, но похоже, что способ доступа к данным может отличаться от проекта к проекту. Еще раз спасибо.   -  person MZawg    schedule 15.11.2018
comment
@mason И тебе того же. Все действительно отличный вклад.   -  person MZawg    schedule 15.11.2018


Ответы (2)


Я не согласен с Терри, потому что:

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

Поэтому я бы создал класс ConnectionManager, который использует строку подключения в качестве параметра конструктора, таким образом, строка подключения не будет «путешествовать» по вашей программе и инкапсулирована в объект «менеджер».

Это плохой пример, но я думаю, что он отлично работает при использовании ADO.NET.

public class ConnectionManager
{
    private string _connectionString;

    public ConnectionManager(string connectionString)
    {
        _connectionString = connectionString;
    }

    public SqlConnection GetConnection()
    {
        return new SqlConnection(_connectionString);
    }
}

Тогда я бы использовал его примерно так:

var connectionManager = new ConnectionManager(connectionString);


using(var con = connectionManager.GetConnection())
{
    // not all operations require .Open()/.Close()

    // multiple queries.
}

using(var con = connectionManager.GetConnection())
{
    // not all operations require .Open()/.Close()

    // multiple other queries.
}

При использовании using соединение будет удалено (вернуто в пул)


Вы даже можете использовать что-то вроде:

public class ConnectionManager
{
    private string _connectionString;

    public ConnectionManager(string connectionString)
    {
        _connectionString = connectionString;
    }

    public void ExecuteNonQuery(string strSqlStatement)
    {
        using(var connection = new SqlConnection(_connectionString))
        using(var command = new SqlCommand(strSqlStatement, connection))
        {
            connection.Open();
            command.ExecuteNonQuery();
        }
    }
}

Что делает:

var connectionManager = new ConnectionManager(connectionString);

connectionManager.ExecuteNonQuery("SELECT * FROM Whatever");

Совет. Обязательно проверьте SqlParameter для предотвращения инъекций SQL

person Jeroen van Langen    schedule 14.11.2018

Я бы не стал создавать, открывать и закрывать соединение в таком методе выполнения sql. Вместо этого я рекомендую создавать соединение и передавать его методу запроса каждый раз, когда требуется запрос, а когда все запросы завершены, закрывать соединение.

person Terry Tyson    schedule 14.11.2018
comment
Проголосовал за @J. Ответ ван Лангена. Мне нравится использование. - person Terry Tyson; 14.11.2018