SQL依赖关系不使用Windows窗体触发

时间:2017-05-01 06:28:54

标签: c# winforms sqldependency

我在Windows窗体应用程序中遇到SQL依赖问题。我在source site找到了一个例子。这个例子很适合作为c#终端应用程序,但是当我将它修改为win表单应用程序时,它不会触发SQL依赖。

这是sql db脚本:

USE master

-- Cleaning up before we start
IF  EXISTS (SELECT name FROM sys.databases WHERE name = N'SqlDependencyTest')
DROP DATABASE [SqlDependencyTest]
IF  EXISTS (SELECT * FROM sys.server_principals WHERE name = N'startUser')
DROP LOGIN [startUser]
IF  EXISTS (SELECT * FROM sys.server_principals WHERE name = N'subscribeUser')
DROP LOGIN [subscribeUser]

-- Creating a database
CREATE DATABASE [SqlDependencyTest]
GO

-- Ensuring that Service Broker is enabled 
ALTER DATABASE [SqlDependencyTest] SET ENABLE_BROKER
GO 

-- Creating users
CREATE LOGIN [startUser] WITH PASSWORD=N'startUser', 
            DEFAULT_DATABASE=[SqlDependencyTest], 
            CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO
CREATE LOGIN [subscribeUser] WITH PASSWORD=N'subscribeUser', 
            DEFAULT_DATABASE=[SqlDependencyTest], CHECK_EXPIRATION=OFF, 
            CHECK_POLICY=OFF
GO

-- Switching to our database
use [SqlDependencyTest]

-- Creating a table. All changes made to the contents of this table will be
-- monitored.
CREATE TABLE Users (ID int, Name nvarchar(50))
GO

/*
 * Creating the users in this database
 *
 * We're going to create two users. One called startUser. This is the user 
 * that is going to have sufficient rights to run SqlDependency.Start.
 * The other user is called subscribeUser, and this is the user that is 
 * going to actually register for changes on the Users-table created earlier.
 * Technically, you're not obligated to make two different users naturally, 
 * but I did here anyway to make sure that I know the minimal rights required
 * for both operations
 *
 * Pay attention to the fact that the startUser-user has a default schema set.
 * This is critical for SqlDependency.Start to work. Below is explained why.
 */
CREATE USER [startUser] FOR LOGIN [startUser] 
WITH DEFAULT_SCHEMA = [startUser]
GO
CREATE USER [subscribeUser] FOR LOGIN [subscribeUser]
GO

/*
 * Creating the schema
 *
 * It is vital that we create a schema specifically for startUser and that we
 * make this user the owner of this schema. We also need to make sure that 
 * the default schema of this user is set to this new schema (we have done 
 * this earlier)
 *
 * If we wouldn't do this, then SqlDependency.Start would attempt to create 
 * some queues and stored procedures in the user's default schema which is
 * dbo. This would fail since startUser does not have sufficient rights to 
 * control the dbo-schema. Since we want to know the minimum rights startUser
 * needs to run SqlDependency.Start, we don't want to give him dbo priviliges.
 * Creating a separate schema ensures that SqlDependency.Start can create the
 * necessary objects inside this startUser schema without compromising 
 * security.
 */
CREATE SCHEMA [startUser] AUTHORIZATION [startUser]
GO

/*
 * Creating two new roles. We're not going to set the necessary permissions 
 * on the user-accounts, but we're going to set them on these two new roles.
 * At the end of this script, we're simply going to make our two users 
 * members of these roles.
 */
EXEC sp_addrole 'sql_dependency_subscriber' 
EXEC sp_addrole 'sql_dependency_starter' 

-- Permissions needed for [sql_dependency_starter]
GRANT CREATE PROCEDURE to [sql_dependency_starter] 
GRANT CREATE QUEUE to [sql_dependency_starter]
GRANT CREATE SERVICE to [sql_dependency_starter]
GRANT REFERENCES on 
CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification]
  to [sql_dependency_starter] 
GRANT VIEW DEFINITION TO [sql_dependency_starter] 

-- Permissions needed for [sql_dependency_subscriber] 
GRANT SELECT to [sql_dependency_subscriber] 
GRANT SUBSCRIBE QUERY NOTIFICATIONS TO [sql_dependency_subscriber] 
GRANT RECEIVE ON QueryNotificationErrorsQueue TO [sql_dependency_subscriber] 
GRANT REFERENCES on 
CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification]
  to [sql_dependency_subscriber] 

-- Making sure that my users are member of the correct role.
EXEC sp_addrolemember 'sql_dependency_starter', 'startUser'
EXEC sp_addrolemember 'sql_dependency_subscriber', 'subscribeUser'

这是c#win表单代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace SqlDependencyTest
{
    public partial class Form1 : Form
    {
        private static string mStarterConnectionString =
@"Data Source=(local);Database=SqlDependencyTest;Persist Security Info=false;
  Integrated Security=false;User Id=startUser;Password=startUser";
        private static string mSubscriberConnectionString =
    @"Data Source=(local);Database=SqlDependencyTest;Persist Security Info=false;
Integrated Security=false;User Id=subscribeUser;Password=subscribeUser";

        public Form1()
        {
            InitializeComponent();

            // Quitting if any exist connection...
            SqlDependency.Stop(mStarterConnectionString);

            // Starting the listener infrastructure...

            SqlDependency.Start(mStarterConnectionString);

            // Registering for changes... 
            RegisterForChanges();



        }

        public void RegisterForChanges()
        {
            // Connecting to the database using our subscriber connection string 
            // and waiting for changes...
            SqlConnection oConnection
                                = new SqlConnection(mSubscriberConnectionString);
            oConnection.Open();
            try
            {
                SqlCommand oCommand = new SqlCommand(
                  "SELECT ID, Name FROM dbo.Users",
                  oConnection);
                SqlDependency oDependency = new SqlDependency(oCommand);
                oDependency.OnChange += new OnChangeEventHandler(OnNotificationChange);

                SqlDataReader objReader = oCommand.ExecuteReader();
                try
                {
                    while (objReader.Read())
                    {
                        // Doing something here...
                        labelText.Text = "reading ok";
                    }
                }
                finally
                {
                    objReader.Close();
                }
            }
            finally
            {
                oConnection.Close();
            }


        }

        public void OnNotificationChange(object caller,
                                            SqlNotificationEventArgs e)
        {
            // Testisting if getting dependency response...
            labelText.Text += e.Info.ToString() + ": " + e.Type.ToString();
            RegisterForChanges();
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            // Quitting...
            SqlDependency.Stop(mStarterConnectionString);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

实际问题不是解雇事件。问题是“labelText.Text”无法在主线程上工作。

此代码解决了我的问题:

    labelText.Invoke((MethodInvoker)delegate {
        labelText.Text = e.Info.ToString() + ": " + e.Type.ToString();
    });