.NET SqlConnection и SqlCommand

#.net #sql #sqlconnection #sqlcommand #dapper

#.net #sql #соединение с sql #sqlcommand #dapper

Вопрос:

Я использую классы SqlConnection и SqlCommand в своем проекте с помощью Dapper ORM, но у меня странная проблема. Когда я использую SqlCommand для вставки строки в таблицу БД, она всегда работает корректно, и когда я выбираю обновленные таблицы формы данных, все в порядке, но после закрытия приложения внесенные мной изменения не фиксируются, как будто данные были сохранены в каком-то кэше. Например, я создал простую таблицу всего с двумя столбцами (идентификатор пользователя (PK) и имя пользователя (уникальное)), и даже в этом случае изменения не сохраняются. Я использую следующий код для вставки строки:

 using (SqlConnection c = new SqlConnection(Settings.Default.UsersConnectionString))
        {
            c.Open();


            using (SqlCommand d = new SqlCommand())
            {
                d.CommandText = "INSERT INTO Users (UserName) VALUES ('SomeName')";
                d.CommandType = System.Data.CommandType.Text;
                d.Connection = c;
                int t = d.ExecuteNonQuery();
            }


            c.Close();
        }
  

Комментарии:

1. Кроме того: строка c.Close(); является избыточной, об этом позаботится предложение outer using .

Ответ №1:

Скорее всего, вы находитесь внутри транзакции, которая не зафиксирована. Возможно, Dapper ORM запустил транзакцию, и вы должны указать ему зафиксировать все изменения.

Комментарии:

1. Чтобы было понятно, я создал простое консольное приложение, используя только единственный приведенный выше код, но проблема все та же.

Ответ №2:

Как я предполагаю, значение по умолчанию для вашего сервера было установлено таким образом, что были включены неявные транзакции. Это означает, что, если вы выполняете команду и ни одна транзакция в данный момент не открыта, SQL Server автоматически запустит транзакцию (как всегда). Но когда команда успешно завершается, эта транзакция остается открытой, и для ее выдачи требуется явная фиксация.

Чтобы определить, так ли это, попробуйте выполнить запрос @@OPTIONS :

 IF @@OPTIONS amp; 2 > 0 
RAISERROR ('Implicit transactions are turned on', 1, 1)
  

Ответ №3:

Этот код в dapper должен быть:

 var name = "SomeName";
int t  = c.Execute("INSERT INTO Users (UserName) VALUES (@name)", new {name});
  

Dapper не выполняет внутреннее управление транзакциями, оно должно быть передано с использованием необязательного параметра транзакции.

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

Комментарии:

1. Есть какой-нибудь способ с помощью Dapper получить последний вставленный идентификатор?

2. c.Query<Decimal>("insert ... select SCOPE_IDENTITY()").First() .. не уверен, что числовое значение (38) точно соответствует int @Developr

3. Мой столбец Identity в SQL равен int. Независимо от того, что я задаю для запроса Dapper (int, long и т.д.), Он выдает мне сообщение «Указанное приведение недопустимо». исключение в строке Dapper: 1104 return (T) val; Нет ли способа сделать это с помощью execute, где я получаю его обратно в качестве выходного параметра, аналогично тому, как работает сохраненный пример процедуры? Не уверен, что это было бы чище, но, по крайней мере, было бы альтернативой.

4. Кстати, недопустимое приведение было вызвано тем, что оно обрабатывало возвращаемый SQL int как десятичный! На данный момент я изменил c.Query<decimal>, и он работает, хотя это немного затруднительно.

5. да, это десятичное число … Dapper является сторонником правильной настройки типов… он не выполняет понижающую или повышающую передачу по дизайну

Ответ №4:

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

 using (SqlConnection c = new SqlConnection(Settings.Default.UsersConnectionString))
{
   c.Open();
   using (SqlTransaction t = c.BeginTransaction("InsertIntoUsers"))
   {
        using (SqlCommand d = new SqlCommand())
        {
            d.CommandText = "INSERT INTO Users (UserName) VALUES ('SomeName')";
            d.CommandType = System.Data.CommandType.Text;
            d.Connection = c;
            int t = d.ExecuteNonQuery();
        }
        t.Commit();
   }
}