Используйте GO (фиксация) в SqlCommand.ExecuteNonQuery ()

Когда я использую SqlCommand.ExecuteNonQuery() и его CommandText имеет GO (фиксацию), я получаю SQLException.

Я удалил его, и SQL работал, но весь SQL содержит множество операторов, и я хотел бы зафиксировать его после выполнения каждого из них. И я не хочу разделять их на несколько SqlCommand объектов.

Есть ли лучшее решение для продолжения фиксации и сохранения уникального объекта SqlCommand?


person Hikari    schedule 18.03.2016    source источник


Ответы (2)


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

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

person Cee McSharpface    schedule 18.03.2016
comment
Спасибо. Извините, я не понял, что вы имеете в виду. Вы предлагаете разделить строку SQL на несколько прогонов, верно? Я хотел сохранить все операции в уникальной строке и выполнить SqlCommand.ExecuteNonQuery() один раз для всех. Неужели это невозможно? - person Hikari; 18.03.2016
comment
Можно, но нужно убрать GO строки. GO - это не то же самое, что фиксация транзакции. GO интерпретируется процессорами пакетных сценариев (osql, SQL Studio script) для выполнения кода, который предшествует ему, как единое целое, поэтому вы можете, например, связать несколько операторов DDL, таких как CREATE VIEW, что в противном случае невозможно. Поэтому, если вы просто удалите GO, вы рискуете, что полученный скрипт завершится ошибкой. Рекомендую петлю. Вы по-прежнему можете повторно использовать тот же объект SqlCommand, просто переназначив CommandText, с незначительным снижением производительности. - person Cee McSharpface; 18.03.2016
comment
Итак, не регистрируются ли журналы в файлах mdf при запуске команды GO? Если это так, я просто удалю его и пусть будет так. - person Hikari; 18.03.2016
comment
да и нет :-) GO не подразумевает транзакцию. вы можете выполнить BEGIN TRAN, затем запустить пакет, а затем ROLLBACK TRAN, чтобы отменить весь пакет (см. здесь. Но если вы вообще не используете транзакцию, каждый вызов SqlCommand.Execute() будет немедленно сохранять результаты обработки данных. Если вы объединяете части скрипта, ранее разделенные GO, будьте осторожны, чтобы не получить неверный сценарий - некоторые операции DDL, такие как CREATE PROCEDURE, не могут выполняться более одного раза в одной команде). - person Cee McSharpface; 18.03.2016

Вот мое решение PowerShell:

[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") > $null
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") > $null
$cnSQL=New-Object System.Data.SqlClient.SqlConnection("Server=$($env:COMPUTERNAME)\$InstanceName;Database=master;User Id=$User;Password=$Pwd")
$cnServer=New-Object Microsoft.SqlServer.Management.Common.ServerConnection($cnSQL)
$strSQL=Get-Content -Path "sqlFile.txt" | Out-String
$cnServer.ExecuteNonQuery($strSQL) > $null
$cnSQL.Close()
person Slogmeister Extraordinaire    schedule 18.07.2016