Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么更改数据库表中的单元格值时不会触发OnChange事件?_C#_.net_Sql Server_Console Application_Sqldependency - Fatal编程技术网

C# 为什么更改数据库表中的单元格值时不会触发OnChange事件?

C# 为什么更改数据库表中的单元格值时不会触发OnChange事件?,c#,.net,sql-server,console-application,sqldependency,C#,.net,Sql Server,Console Application,Sqldependency,在过去的24小时里,我一直在编写这个代码,但它不起作用 如果我修改服务表中的单元格,我希望OnChange事件被命中,但不管我做什么,它都不会被命中 我已经在数据库上启用了ServicesBroker,但它仍然不起作用 代码: 使用“编辑更多”或“更新查询”对数据库进行更改 下面是一个基于您的代码的工作示例,该代码在触发事件时显示SqlNotificationEventArgs值,并且仅在有效时重新订阅 using System; using System.Data; using System.

在过去的24小时里,我一直在编写这个代码,但它不起作用

如果我修改服务表中的单元格,我希望OnChange事件被命中,但不管我做什么,它都不会被命中

我已经在数据库上启用了ServicesBroker,但它仍然不起作用

代码:

使用“编辑更多”或“更新查询”对数据库进行更改


下面是一个基于您的代码的工作示例,该代码在触发事件时显示
SqlNotificationEventArgs
值,并且仅在有效时重新订阅

using System;
using System.Data;
using System.Data.SqlClient;

class Program
{

    static void Main(string[] args)
    {

        SqlDependency.Start(Utility.getConnectionString());

        GetDataWithSqlDependency();
        Console.WriteLine("Waiting for data changes");
        Console.WriteLine("Press any key to quit");
        Console.ReadKey();

        SqlDependency.Stop(Utility.getConnectionString());

    }

    static void GetDataWithSqlDependency()
    {

        using (var connection = new SqlConnection(Utility.getConnectionString()))
        using (var cmd = new SqlCommand(@"SELECT [Services].[ServiceName], [Services].[ServicePrice] from dbo.Services;", connection))
        {
            var dependency = new SqlDependency(cmd);
            dependency.OnChange += new OnChangeEventHandler(OnDependencyChange);
            connection.Open();
            cmd.ExecuteReader().Dispose();
        }

    }
    static void OnDependencyChange(object sender, SqlNotificationEventArgs e)
    {

        Console.WriteLine($"OnDependencyChange Event fired. SqlNotificationEventArgs: Info={e.Info}, Source={e.Source}, Type={e.Type}");

        if ((e.Info != SqlNotificationInfo.Invalid)
            && (e.Type != SqlNotificationType.Subscribe))
        {
            SqlDependency.Start(Utility.getConnectionString());
            GetDataWithSqlDependency();
            Console.WriteLine($"Data changed.");
        }
        else
        {
            Console.WriteLine("SqlDependency not restarted");
        }

    }

}

static class Utility
{
    public static string getConnectionString()
    {
        return @"Data Source=.;Initial Catalog=YourDatabase;Application Name=SqlDependencyExample;Integrated Security=SSPI";
    }

}
这是测试数据库的DDL:

CREATE DATABASE YourDatabase;
GO
ALTER DATABASE YourDatabase SET ENABLE_BROKER;
GO
USE YourDatabase;
GO
CREATE TABLE dbo.Services(
      ServiceName varchar(100) NOT NULL 
        CONSTRAINT PK_Services PRIMARY KEY
    , ServicePrice decimal(10,2) NOT NULL
);
GO
这些查询触发OnChanged事件:

INSERT INTO dbo.Services VALUES('SomeService', 1.00);
GO
UPDATE dbo.Services SET ServicePrice = 2.00 WHERE ServiceName = 'SomeService';
GO
DELETE FROM dbo.Services WHERE ServiceName = 'SomeService';
GO
编辑:

如果您使用最低权限帐户(最佳实践)运行应用程序,下面是一个示例脚本,用于授予
SqlDependency
所需的最低权限

--create user for schema ownership
CREATE USER SqlDependencySchemaOwner WITHOUT LOGIN;
GO
--create schema for SqlDependency objects
CREATE SCHEMA SqlDependency AUTHORIZATION SqlDependencySchemaOwner;
GO

--add existing login as a minimally privileged database user with default schema SqlDependency
CREATE USER YourLogin WITH DEFAULT_SCHEMA = SqlDependency;

--grant user control permissions on SqlDependency schema
GRANT CONTROL ON SCHEMA::SqlDependency TO YourLogin;

--grant user impersonate permissions on SqlDependency schema owner
GRANT IMPERSONATE ON USER::SqlDependencySchemaOwner TO YourLogin;
GO

--grant database permissions needed to create and use SqlDependency objects
GRANT CREATE PROCEDURE TO YourLogin;
GRANT CREATE QUEUE TO YourLogin;
GRANT CREATE SERVICE TO YourLogin;
GRANT REFERENCES ON
    CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification] TO YourLogin;
GRANT VIEW DEFINITION TO YourLogin;
GRANT SELECT to YourLogin;
GRANT SUBSCRIBE QUERY NOTIFICATIONS TO YourLogin;
GRANT RECEIVE ON QueryNotificationErrorsQueue TO YourLogin;
GO

--grant permissions on user objects used by application
GRANT SELECT ON dbo.Services TO YourLogin;
GO
完成了

这只是因为我没有使用sa作为登录名。只有我将数据库更改为sa,并在连接字符串中使用它。成功了

讨论:

问题:


它可能来自映射到Windows帐户的dbo,该帐户有时无效。”dbo'实际上是创建数据库的用户。例如,如果我在工作时在笔记本电脑上的SQL实例上创建示例,那么就会出现这个问题,然后回家继续。在家里,我没有访问域ActiveDirectory的权限,而示例突然停止工作,因为“dbo”实际上是我的Windows帐户,不再可用。“dbo”发送的消息(如通知)位于sys.transmissions\u队列中,状态为“无法从域控制器检索有关用户“…”的信息”。在数据库中以USER='dbo'的身份运行EXECUTE也会显示发生相同的错误。这种情况下的修复方法是将“dbo”更改为有效的登录名,例如,通过在数据库上运行alterauthorization::[dbname]到[sa]

:SqlDependency允许您在数据库中的原始数据发生更改时接收通知,以便刷新缓存。@TaW:是的,但它不会发生在您的代码中您是否对数据库数据进行了任何更改??我使用“更新查询”或“编辑”模式直接在数据库中进行更改我没有做过任何更改工作,但仍然不意味着你说这个示例代码不适合你?是否触发了
OnDependencyChange
方法?如果是,将为
OnDependencyChange
事件参数显示哪些值?完成。这只是因为我没有使用sa作为登录。只有我将数据库更改为sa,并在连接字符串中使用它。它起作用了。@jameel,如果非系统管理员登录没有所需的权限,我会期望出现
SqlException
。我用非系统管理员对SqlDependency所需的最低权限更新了我的答案。谢谢,但我已经将它分配给了拥有所有权限但仍然只能使用“sa”的用户。为什么?@jameel,你的意思是你授予了用户我答案中所列的确切权限,但它不起作用?你的答案没有为其他答案和评论添加任何有用的内容。简单地转储一堆代码也无助于理解问题所在。。。
  using (SqlConnection conn = new SqlConnection(connectionString))
        {
            conn.Open();

            SqlDependency.Start(connectionString);

            string commandText = "select ID, status from dbo.VendorSetup";

            SqlCommand cmd = new SqlCommand(commandText, conn);

            SqlDependency dependency = new SqlDependency(cmd);

            dependency.OnChange += new OnChangeEventHandler(dbChangeNotification);

            var reader = cmd.ExecuteReader();

            while (reader.Read())
            {
                var employee = new VendorSetup
                {
                    ID = Convert.ToInt32(reader["ID"]),
                    status = reader["status"].ToString(),
                    //Age = Convert.ToInt32(reader["Age"])
                };

                employees.Add(employee);
            }
        }

        return employees;
    }

    private void dbChangeNotification(object sender, SqlNotificationEventArgs e)
    {
        _hubcontext.Clients.All.SendAsync("displayNotification");
    }
  using (SqlConnection conn = new SqlConnection(connectionString))
        {
            conn.Open();

            SqlDependency.Start(connectionString);

            string commandText = "select ID, status from dbo.VendorSetup";

            SqlCommand cmd = new SqlCommand(commandText, conn);

            SqlDependency dependency = new SqlDependency(cmd);

            dependency.OnChange += new OnChangeEventHandler(dbChangeNotification);

            var reader = cmd.ExecuteReader();

            while (reader.Read())
            {
                var employee = new VendorSetup
                {
                    ID = Convert.ToInt32(reader["ID"]),
                    status = reader["status"].ToString(),
                    //Age = Convert.ToInt32(reader["Age"])
                };

                employees.Add(employee);
            }
        }

        return employees;
    }

    private void dbChangeNotification(object sender, SqlNotificationEventArgs e)
    {
        _hubcontext.Clients.All.SendAsync("displayNotification");
    }