Поиск…


Вступление

ADO (объекты данных ActiveX) .Net - это инструмент, предоставляемый Microsoft, который обеспечивает доступ к источникам данных, таким как SQL Server, Oracle и XML через свои компоненты. .Net-приложения могут извлекать, создавать и обрабатывать данные, как только они подключены к источнику данных через ADO.Net с соответствующими привилегиями.

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

замечания

Замечание о параметризации SQL с Parameters.AddWithValue AddWithValue : AddWithValue никогда не является хорошей отправной точкой. Этот метод основан на выводе типа данных из того, что передается. При этом вы можете оказаться в ситуации, когда преобразование не позволяет вашему запросу использовать индекс . Обратите внимание, что некоторые типы данных SQL Server, такие как char / varchar (без предшествующих «n») или date , не имеют соответствующего типа данных .NET. В таких случаях вместо этого следует использовать Add с правильным типом данных .

Выполнение операторов SQL как команды

// Uses Windows authentication. Replace the Trusted_Connection parameter with
// User Id=...;Password=...; to use SQL Server authentication instead. You may
// want to find the appropriate connection string for your server.
string connectionString = @"Server=myServer\myInstance;Database=myDataBase;Trusted_Connection=True;"

string sql = "INSERT INTO myTable (myDateTimeField, myIntField) " +
    "VALUES (@someDateTime, @someInt);";

// Most ADO.NET objects are disposable and, thus, require the using keyword.
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(sql, connection))
{
    // Use parameters instead of string concatenation to add user-supplied
    // values to avoid SQL injection and formatting issues. Explicitly supply datatype.

    // System.Data.SqlDbType is an enumeration. See Note1
    command.Parameters.Add("@someDateTime", SqlDbType.DateTime).Value = myDateTimeVariable;
    command.Parameters.Add("@someInt", SqlDbType.Int).Value = myInt32Variable;

    // Execute the SQL statement. Use ExecuteScalar and ExecuteReader instead
    // for query that return results (or see the more specific examples, once
    // those have been added).

    connection.Open();
    command.ExecuteNonQuery();
}

Примечание 1: см. Перечисление SqlDbType для варианта MSFT SQL Server.

Примечание 2: см. Перечисление MySqlDbType для варианта, специфичного для MySQL.

Лучшие практики - выполнение заявлений Sql

public void SaveNewEmployee(Employee newEmployee)
{
    // best practice - wrap all database connections in a using block so they are always closed & disposed even in the event of an Exception
    // best practice - retrieve the connection string by name from the app.config or web.config (depending on the application type) (note, this requires an assembly reference to System.configuration)
    using(SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionName"].ConnectionString))
    {
        // best practice - use column names in your INSERT statement so you are not dependent on the sql schema column order
        // best practice - always use parameters to avoid sql injection attacks and errors if malformed text is used like including a single quote which is the sql equivalent of escaping or starting a string (varchar/nvarchar)
        // best practice - give your parameters meaningful names just like you do variables in your code
        using(SqlCommand sc = new SqlCommand("INSERT INTO employee (FirstName, LastName, DateOfBirth /*etc*/) VALUES (@firstName, @lastName, @dateOfBirth /*etc*/)", con))
        {
            // best practice - always specify the database data type of the column you are using
            // best practice - check for valid values in your code and/or use a database constraint, if inserting NULL then use System.DbNull.Value
            sc.Parameters.Add(new SqlParameter("@firstName", SqlDbType.VarChar, 200){Value = newEmployee.FirstName ?? (object) System.DBNull.Value});
            sc.Parameters.Add(new SqlParameter("@lastName", SqlDbType.VarChar, 200){Value = newEmployee.LastName ?? (object) System.DBNull.Value});

            // best practice - always use the correct types when specifying your parameters, Value is assigned to a DateTime instance and not a string representation of a Date
            sc.Parameters.Add(new SqlParameter("@dateOfBirth", SqlDbType.Date){ Value = newEmployee.DateOfBirth });

            // best practice - open your connection as late as possible unless you need to verify that the database connection is valid and wont fail and the proceeding code execution takes a long time (not the case here)
            con.Open();
            sc.ExecuteNonQuery();
        }

        // the end of the using block will close and dispose the SqlConnection
        // best practice - end the using block as soon as possible to release the database connection
    }
}

// supporting class used as parameter for example
public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
}

Лучшая практика работы с ADO.NET

  • Правило большого пальца - это открыть соединение для минимального времени. Закройте соединение явным образом после завершения процедуры. Это вернет объект подключения обратно в пул соединений. Пул соединений по умолчанию max size = 100. Поскольку объединение пулов повышает производительность физического подключения к SQL Server. Пул соединений в SQL Server
  • Оберните все подключения к базе данных в используемом блоке, чтобы они всегда закрывались и удалялись даже в случае исключения. См. Использование Statement (C # Reference) для получения дополнительной информации об использовании операторов
  • Извлеките строки подключения по имени из app.config или web.config (в зависимости от типа приложения)
  • Всегда используйте параметры для входящих значений для
    • Избегайте атак sql injection
    • Избегайте ошибок, если используется неверный текст, например, включая одиночную кавычку, которая является эквивалентом sql для экранирования или запуска строки (varchar / nvarchar)
    • Предоставление поставщику базы данных повторного использования планов запросов (не поддерживаемых всеми поставщиками баз данных), что повышает эффективность
  • При работе с параметрами
    • Тип параметра Sql и несоответствие размера являются общей причиной отказа вставки / обновления / выбора
    • Дайте параметры Sql значимым именам так же, как и переменные в коде.
    • Укажите тип данных базы данных используемого столбца, это гарантирует, что неправильные типы параметров не используются, что может привести к неожиданным результатам
    • Подтвердите свои входящие параметры, прежде чем передавать их в команду (как говорится, « мусор, мусор »). Проверять входящие значения как можно раньше в стеке
    • Используйте правильные типы при назначении значений параметров, например: не назначайте строковое значение DateTime, вместо этого присвойте фактическому экземпляру DateTime значение параметра
    • Укажите размер параметров строкового типа. Это связано с тем, что SQL Server может повторно использовать планы выполнения, если параметры соответствуют типу и размеру. Использовать -1 для MAX
    • Не используйте метод AddWithValue , основная причина заключается в том, что очень легко забыть указать тип параметра или точность / масштаб, когда это необходимо. Для получения дополнительной информации см. Можно ли уже остановить использование AddWithValue?
  • При использовании соединений с базой данных
    • Откройте соединение как можно позже и закройте его как можно скорее. Это общее руководство при работе с любым внешним ресурсом
    • Никогда не обменивайтесь экземплярами подключения к базе данных (пример: наличие одного хост-узла является общим экземпляром типа SqlConnection ). Если ваш код всегда создает новый экземпляр подключения базы данных, тогда необходимо, чтобы код вызова удалил его и «выбросил», когда это будет сделано. Причиной этого является
      • У большинства поставщиков баз данных есть своего рода объединение пулов, поэтому создание новых управляемых соединений дешево
      • Он устраняет любые будущие ошибки, если код начинает работать с несколькими потоками

Использование общих интерфейсов для абстрагирования отдельных классов поставщиков

var providerName = "System.Data.SqlClient";    //Oracle.ManagedDataAccess.Client, IBM.Data.DB2
var connectionString = "{your-connection-string}";
//you will probably get the above two values in the ConnectionStringSettings object from .config file

var factory = DbProviderFactories.GetFactory(providerName);
using(var connection = factory.CreateConnection()) {    //IDbConnection
    connection.ConnectionString = connectionString;
    connection.Open();
    
    using(var command = connection.CreateCommand()) {    //IDbCommand
        command.CommandText = "{query}";
        
        using(var reader = command.ExecuteReader()) {    //IDataReader
            while(reader.Read()) {
                ...
            }
        }
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow