SSMS
 sql >> Teknologi Basis Data >  >> Database Tools >> SSMS

Objek SMO SSMS:Dapatkan hasil kueri

Hal termudah adalah dengan mencetak nomor yang Anda dapatkan kembali untuk ExecuteNonQuery :

int rowsAffected = server.ConnectionContext.ExecuteNonQuery(/* ... */);
if (rowsAffected != -1)
{
     Console.WriteLine("{0} rows affected.", rowsAffected);
}

Ini seharusnya bekerja, tetapi tidak akan menghormati SET NOCOUNT pengaturan sesi/cakupan saat ini.

Jika tidak, Anda akan melakukannya seperti yang Anda lakukan dengan ADO.NET "polos". Jangan gunakan ServerConnection.ExecuteNonQuery() metode, tetapi buat SqlCommand objek dengan mengakses SqlConnection yang mendasarinya obyek. Pada itu berlangganan StatementCompleted acara.

using (SqlCommand command = server.ConnectionContext.SqlConnectionObject.CreateCommand())
{
    // Set other properties for "command", like StatementText, etc.

    command.StatementCompleted += (s, e) => {
         Console.WriteLine("{0} row(s) affected.", e.RecordCount);
    };

    command.ExecuteNonQuery();
}

Menggunakan StatementCompleted (sebagai gantinya, katakanlah, secara manual mencetak nilai yang ExecuteNonQuery() dikembalikan) memiliki manfaat bahwa ia bekerja persis seperti SSMS atau SQLCMD.EXE akan:

  • Untuk perintah yang tidak memiliki ROWCOUNT tidak akan dipanggil sama sekali (mis. GO, USE).
  • Jika SET NOCOUNT ON telah disetel, itu tidak akan dipanggil sama sekali.
  • Jika SET NOCOUNT OFF telah disetel, itu akan dipanggil untuk setiap pernyataan di dalam kumpulan.

(Bilah Samping:sepertinya StatementCompleted persis seperti yang dibicarakan oleh protokol TDS ketika DONE_IN_PROC peristiwa disebutkan; lihat Keterangan dari perintah SET NOCOUNT pada MSDN.)

Secara pribadi, saya telah menggunakan pendekatan ini dengan sukses di "klon" saya sendiri dari SQLCMD.EXE.

PERBARUI :Perlu dicatat, bahwa pendekatan ini (tentu saja) mengharuskan Anda untuk membagi skrip/pernyataan input secara manual di GO pemisah, karena Anda kembali menggunakan SqlCommand.Execute*() yang tidak dapat menangani banyak batch sekaligus. Untuk ini, ada beberapa opsi:

  • Pisahkan input secara manual pada baris yang dimulai dengan GO (peringatan:GO bisa dipanggil seperti GO 5 , misalnya, untuk mengeksekusi kumpulan sebelumnya 5 kali).
  • Gunakan ManagedBatchParser class/library untuk membantu Anda membagi input menjadi batch tunggal, terutama mengimplementasikan ICommandExecutor.ProcessBatch dengan kode di atas (atau yang serupa).

Saya memilih opsi yang lebih baru, yang cukup berhasil, mengingat itu tidak didokumentasikan dengan baik dan contoh jarang (google sedikit, Anda akan menemukan beberapa barang, atau menggunakan reflektor untuk melihat bagaimana Majelis SMO menggunakan kelas itu) .

Manfaat (dan mungkin beban) menggunakan ManagedBatchParser adalah, bahwa itu juga akan mengurai semua konstruksi skrip T-SQL lainnya (ditujukan untuk SQLCMD.EXE ) untuk kamu. Termasuk::setvar , :connect , :quit , dll. Anda tidak perlu mengimplementasikan ICommandExecutor masing-masing anggota, jika skrip Anda tidak menggunakannya, tentu saja. Namun perlu diingat bahwa Anda mungkin tidak dapat menjalankan skrip "sewenang-wenang".

Nah, apakah itu menempatkan Anda. Dari "pertanyaan sederhana" tentang cara mencetak "... baris terpengaruh" hingga fakta bahwa itu tidak sepele untuk dilakukan dengan cara yang kuat dan umum (mengingat pekerjaan latar belakang diperlukan). YMMV, semoga berhasil.

Pembaruan tentang Penggunaan ManagedBatchParser

Tampaknya tidak ada dokumentasi atau contoh yang baik tentang cara mengimplementasikan IBatchSource , inilah yang saya gunakan.

internal abstract class BatchSource : IBatchSource
{
    private string m_content;

    public void Populate()
    {
        m_content = GetContent();
    }

    public void Reset()
    {
        m_content = null;
    }

    protected abstract string GetContent();

    public ParserAction GetMoreData(ref string str)
    {
        str = null;

        if (m_content != null)
        {
            str = m_content;
            m_content = null;
        }

        return ParserAction.Continue;
    }
}

internal class FileBatchSource : BatchSource
{
    private readonly string m_fileName;

    public FileBatchSource(string fileName)
    {
        m_fileName = fileName;
    }

    protected override string GetContent()
    {
        return File.ReadAllText(m_fileName);
    }
}

internal class StatementBatchSource : BatchSource
{
    private readonly string m_statement;

    public StatementBatchSource(string statement)
    {
        m_statement = statement;
    }

    protected override string GetContent()
    {
        return m_statement;
    }
}

Dan beginilah cara Anda menggunakannya:

var source = new StatementBatchSource("SELECT GETUTCDATE()");
source.Populate();

var parser = new Parser(); 
parser.SetBatchSource(source);
/* other parser.Set*() calls */

parser.Parse();

Perhatikan bahwa kedua implementasi, baik untuk pernyataan langsung (StatementBatchSource ) atau untuk file (FileBatchSource ) memiliki masalah bahwa mereka membaca teks lengkap sekaligus ke dalam memori. Saya punya satu kasus di mana itu meledak, memiliki skrip besar(!) dengan trilyunan INSERT yang dihasilkan pernyataan. Meskipun menurut saya itu bukan masalah praktis, SQLCMD.EXE bisa menanganinya. Tetapi untuk kehidupan saya, saya tidak tahu bagaimana tepatnya, Anda perlu membentuk potongan yang dikembalikan untuk IBatchParser.GetContent() sehingga parser masih dapat bekerja dengan mereka (sepertinya mereka perlu pernyataan lengkap, yang akan mengalahkan tujuan parse sejak awal...).




  1. DBeaver
  2.   
  3. phpMyAdmin
  4.   
  5. Navicat
  6.   
  7. SSMS
  8.   
  9. MySQL Workbench
  10.   
  11. SQLyog
  1. Ganti nama tab secara manual di SSMS

  2. Bagaimana cara menyegarkan cache intellisense SQL Server Management Studio secara otomatis?

  3. Tidak dapat menginstal database adventureworks 2012 - Kesalahan sistem operasi 5:Akses ditolak

  4. ALTER DATABASE gagal karena kunci tidak dapat ditempatkan pada database

  5. SQL Server Management Studio TIDAK mengizinkan saya membuat beberapa kunci asing ke beberapa kunci utama