当QUOTED_IDENTIFIER设置为OFF时,SQL INSERT / UPDATE / DELETE失败,同时使用SqlDependancy监视表

时间:2015-06-18 10:47:25

标签: c# sql sql-server sqldependency

因为标题说当QUOTED_IDENTIFIER设置为OFF时DML查询失败,同时使用SqlDependancy监视表。 我在INSERT / UPDATE / DELETE语句中遇到以下错误:

  • INSERT失败,因为以下SET选项的设置不正确:'QUOTED_IDENTIFIER'。验证SET选项是否正确,可用于计算列和/或筛选索引和/或查询通知和/或XML数据类型方法和/或空间索引操作的索引视图和/或索引。
  • UPDATE失败,因为以下SET选项的设置不正确:'QUOTED_IDENTIFIER'。验证SET选项是否正确,可用于计算列和/或筛选索引和/或查询通知和/或XML数据类型方法和/或空间索引操作的索引视图和/或索引。
  • DELETE失败,因为以下SET选项的设置不正确:'QUOTED_IDENTIFIER'。验证SET选项是否正确,可用于计算列和/或筛选索引和/或查询通知和/或XML数据类型方法和/或空间索引操作的索引视图和/或索引。

以下是复制问题的代码,它是我能够创建的最小代码。

我使用了SQL 2008 R2和Visual Studio 2013(C#使用.Net Framework v4.5.1)

首先创建一个测试数据库,表并填充它。


USE [master]
GO

CREATE DATABASE [BUG0001]
GO

ALTER DATABASE [BUG0001] SET ENABLE_BROKER
GO

USE [BUG0001]
GO

CREATE TABLE [dbo].[Test]
(
    [RowVersion]
        ROWVERSION,

    [TestId]
        INT
        NOT NULL,

    [Flipper]
        BIT
        NOT NULL,

    CONSTRAINT [PK_dbo_Test_TestId] PRIMARY KEY ([TestId])
)
GO

INSERT INTO [dbo].[Test] ([TestId], [Flipper])
    VALUES (1, 0);

现在创建一个控制台应用程序并运行它(记得为数据库设置连接字符串)


using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BUG0001
{
    class Program
    {
        const string CN_STRING = "Server=TESTSERVER;Database=BUG0001;Trusted_Connection=True;";
        const string SQL_DATA = "SELECT [RowVersion], [TestId], [Flipper] FROM [dbo].[Test] WHERE [RowVersion] > @LastRowVersion ORDER BY [RowVersion];";

        const int FIELD_ROW_VERSION = 0;
        const int FIELD_TEST_ID = 1;
        const int FIELD_FLIPPER = 2;

        static SqlConnection cn = null;
        static byte[] lastRowVersion = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };

        static void Main(string[] args)
        {
            SqlDependency.Start(CN_STRING);

            using (cn = new SqlConnection(CN_STRING))
            {
                cn.Open();

                Console.WriteLine("Press any key to exit.");
                Console.WriteLine();

                GetData();

                ConsoleKeyInfo keyInfo;

                do { keyInfo = Console.ReadKey(true); }
                while (keyInfo.Key == ConsoleKey.LeftWindows || keyInfo.Key == ConsoleKey.RightWindows);

                cn.Close();
            }

            SqlDependency.Stop(CN_STRING);
        }

        static void GetData()
        {
            using (var cmd = cn.CreateCommand())
            {
                cmd.CommandText = SQL_DATA;
                cmd.Parameters.Add(new SqlParameter("@LastRowVersion", lastRowVersion));

                /* The SqlDependency is a one event only mechignisum and must be reset each time the event is triggered. */
                var depenency = new SqlDependency(cmd);
                depenency.OnChange += depenency_OnChange;

                RenderResults(cmd);
            }
        }

        static void depenency_OnChange(object sender, SqlNotificationEventArgs e)
        {
            Console.WriteLine(e.Info);
            Console.WriteLine(e.Source);
            Console.WriteLine(e.Type);
            Console.WriteLine();

            GetData();
        }

        static void RenderResults(SqlCommand cmd)
        {
            try
            {
                using (var reader = cmd.ExecuteReader())
                {
                    foreach (DbDataRecord record in reader)
                    {
                        var rowVersion = (byte[])record.GetValue(FIELD_ROW_VERSION);

                        Console.WriteLine(
                            "[RowVersion] = 0x{0}\r\n[TestId] = '{1}'\r\n[Flipper] = '{2}'\r\n",
                            BitConverter.ToString(rowVersion).Replace("-", string.Empty),
                            record.GetInt32(FIELD_TEST_ID),
                            record.GetBoolean(FIELD_FLIPPER)
                        );

                        lastRowVersion = rowVersion;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
}

现在使用SQL Management Studio运行以下命令以获取错误


--SET QUOTED_IDENTIFIER ON /* Without Error */
SET QUOTED_IDENTIFIER OFF /* With Error */
GO

INSERT INTO [dbo].[Test] ([TestId], [Flipper]) VALUES (2, 0);
GO

UPDATE [dbo].[Test] SET [Flipper] = ~[Flipper] WHERE [TestId] = 1
GO

SELECT * FROM [dbo].[Test]
GO

DELETE FROM [dbo].[Test] WHERE [TestId] = 2
GO

SELECT * FROM [dbo].[Test]
GO

就像你对医生说“当我触摸它时疼痛”并且医生回应“好不要触摸它”我知道我可以在我的应用程序中使用“SET QUOTED_IDENTIFIER ON”但我正在监控由另一个应用程序创建和维护的表,无法控制它们如何设置QUOTED_IDENTIFIER。

有没有办法监控表而不会导致上面显示的问题?

也有人可以解释为什么会这样吗?

我在这里也发现了一个类似的问题(SQL Server: INSERT/UPDATE/DELETE failed because the following SET options have incorrect settings: ‘QUOTED_IDENTIFIER’),但没有提供如何处理这个问题的线索。

0 个答案:

没有答案