GVKun编程网logo

SQLDependency +服务代理(sql server 代理服务)

3

本文的目的是介绍SQLDependency+服务代理的详细情况,特别关注sqlserver代理服务的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解SQLDepende

本文的目的是介绍SQLDependency +服务代理的详细情况,特别关注sql server 代理服务的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解SQLDependency +服务代理的机会,同时也不会遗漏关于.NET 2.0 SqlDependency 快速上手指南、asp.net中的SqlDependency、c# – SqlDependency简单选择查询总是返回“无效”、c# – 使用SqlDependency导致不断更新的知识。

本文目录一览:

SQLDependency +服务代理(sql server 代理服务)

SQLDependency +服务代理(sql server 代理服务)

当某些表中的数据更改时,我正在使用SqlDependency来获取通知。

    private void subscribeBroker()    {        using (var conn = new SqlConnection(connString))        {            conn.Open();            var cmd = new SqlCommand("SELECT text FROM dbo.Test");            cmd.Connection = conn;            var dependency = new SqlDependency(cmd);            dependency.OnChange += dependency_OnChange;            SqlDependency.Start(connString);            cmd.ExecuteNonQuery();        }    }    void dependency_OnChange(object sender, SqlNotificationEventArgs e)    {        //Do something...        subscribeBroker();    }

它正在工作,但是我有一些问题。

1)我没有找到一种方法来获取更改哪一行的信息。我需要从整个表中读取所有数据,以查看有什么不同。有没有办法获取这些信息?(主要ID,或其他)或使用与SqlDependency不同的方法?

2)如果“某人”非常快地更改数据该怎么办。某些更改可能不会得到通知吗?(我担心通知和再次订阅之间的时间。

谢谢你。

答案1

小编典典

关于1-查询通知会通知您有关事实,即某些更改。如果要获取自上次以来发生的更改,则可以使用timestamp列。

关于2-查询通知会通知您有关更改的信息,然后将其删除。然后您再次订阅通知。从删除到创建通知之间的时间就是不发送有关更改的通知的时间。

当数据不经常更改时,查询通知更适合这种情况。例如-
一些现金分类值。因此,您在某个表中订阅更改,等待更改,然后在发生更改时获得最新版本的数据。应该考虑到查询通知还使用服务器资源,因此,如果您的表很大,并且想对一些小的数据子集进行更改,那么很多查询的性能都会受到影响(例如索引视图)。

如果您需要根据更改的数据采取某些措施,并且每个更改都很重要,那么我猜触发器+服务代理可能会更有效。或者,根据您的需要,更改数据捕获。

.NET 2.0 SqlDependency 快速上手指南

.NET 2.0 SqlDependency 快速上手指南

此文以 SQL Server 2005 上实现为准,SQL Server 2000 因为实现机制不同,请查阅相关资料。

 

       步骤一:在 SQL Server 2005 上执行 ALTER DATABASE <DatabaseName> SET ENABLE_BROKER; 语句让相应的数据库启用监听服务,以便支持 SqlDependency 特性。

       这条语句最好在数据库未执行任何事务的情况下执行。

 

       步骤二:调用 SqlDependency.Start(String strConnectionString) 方法,在应用程序端启用依赖监听器。

       该方法的参数为一个数据库的连接字符串,该数据库必须已经执行过步骤一的操作。

       对于同一连接字符串,若已经执行过该语句,再次执行不会发生任何异常,但返回值会为 False.

       如果是在 Web 程序中使用,建议可以将该语句放在 Application_Start 事件中执行。

       监听是基于数据库的,而依赖才可以基于表或者查询。

 

       步骤三:该步骤分别有两种不同的做法。该阶段必须注意步骤。

              方法 A:建立连接对象,再创建一个 SqlCommand 实例,创建 SqlCacheDependency 实例,在这步之后再调用 Command 对象来获取数据(这个顺序很重要)。之后调用 Cache 的 Insert 语句建立一个依赖于一个具体查询数据集的 Cache 项。


             SqlConnection conn = new SqlConnection(strConnection);

         SqlCommand command = new SqlCommand(strCommandText, conn);

         SqlCacheDependency dependency = new SqlCacheDependency(command);

        

         // 注册方法到委托,该委托是

         CacheItemRemovedCallback onRemove = new CacheItemRemovedCallback(RemovedCallback);

         // 新增或修改一条缓存记录

         Cache.Insert(strCacheKey, objAppCache, dependency, absoluteExpiration, slidingExpiration, CacheItemPriority.Default, onRemove);

 

          方法 B:建立连接对象,再创建一个 SqlCommand 实例,最后创建 SqlDependency 实例。定义 SqlDependency 的委托 OnChange,当数据发生改变时做出相应的处理(比如清除 Cache)。

              SqlConnection conn = new SqlConnection(strConnection);

         SqlCommand command = new SqlCommand(strCommandText, conn);

         SqlCacheDependency dependency = new SqlCacheDependency(command);

             

              dependency.OnChange += new OnChangeEventHandler(Dependency_OnChange);

 

 

     注意事项:

       不知道是不是还存在 BUG,我在项目开发中遇到一些奇怪的现象。同样的代码,在有的机器上运行则能捕捉到变化,有的则完全没反应;也有时会出现 Cache 刚建立就反复发生依赖改变的事件。偶尔 Cache 还会数据发生变化却不引发事件。

       但从最终项目实施的情况看,似乎都只是某些机器环境造成的不确定因素?这个无法确定。不过起码数据库端是否正常启用,可以通过 SQL Server Profiler 来查看监视。

asp.net中的SqlDependency

asp.net中的SqlDependency

我正在使用sqlDependency来控制我的缓存.我想用它来监控几个表(大约10个).每个观看的表应该有一个sqlDependency.

我应该为每个代码创建这样的代码:

public void CreateDependency_Table()
    {
        if (connectionStringSettings != null)
        {
            using (sqlConnection conn = new sqlConnection(connectionStringSettings.ConnectionString))
            {
                conn.open();
                using (sqlCommand cmd = new sqlCommand("SELECT id from dbo.Table",conn))
                {
                    cmd.Notification = null;
                    sqlDependency sqlDependency = new sqlDependency(cmd);
                    sqlDependency.OnChange += new OnChangeEventHandler(sqlDep_Table_OnChange);
                    using (sqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
                    {
                    }
                }
            }
        }
    }

和:

private void sqlDep_Table_OnChange(object sender,sqlNotificationEventArgs e)
    {
        sqlDependency dependency = (sqlDependency)sender;
        dependency.OnChange -= sqlDep_Table_OnChange;

        MyCacheWhatever.Clear();

        //Re-attach dependency
        CreateDependency_Table();
    }

或者我可以在它们之间重复使用它喜欢连接?

这是设置多个通知的首选方式吗?

解决方法

在这里,我将向您展示一个可以帮助您的linq扩展:
public static class LinqExtensions
 {
  private static ILog _Log = LogManager.GetLogger(MethodInfo.GetCurrentMethod().DeclaringType);

  [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design","CA1031:DoNotCatchGeneralExceptionTypes")]
  public static IList<T> LinqCache<T>(this Table<T> query) where T : class
        {
            string tableName = query.Context.Mapping.GetTable(typeof(T)).TableName;
   IList<T> result = HttpContext.Current.Cache[tableName] as List<T>;

            if (result == null)
            {
    try
    {
     using (sqlConnection cn = new sqlConnection(query.Context.Connection.ConnectionString))
     {
      cn.open();
      sqlCommand cmd = new sqlCommand(query.Context.GetCommand(query).CommandText,cn);
      cmd.Notification = null;
      cmd.NotificationAutoEnlist = true;

      _Log.DebugFormat("Attempting to enable sql cache dependency notifications for table {0}",tableName);

      sqlCacheDependencyAdmin.EnableNotifications(query.Context.Connection.ConnectionString);

      string[] tables = sqlCacheDependencyAdmin.GetTablesEnabledForNotifications(query.Context.Connection.ConnectionString);

      if (!tables.Contains(tableName))
       sqlCacheDependencyAdmin.EnableTableForNotifications(query.Context.Connection.ConnectionString,tableName);

      _Log.DebugFormat("sql cache dependency notifications for table {0} is enabled.",tableName);

      sqlCacheDependency dependency = new sqlCacheDependency(cmd);
      cmd.ExecuteNonQuery();

      result = query.ToList();
      HttpContext.Current.Cache.Insert(tableName,result,dependency);

      _Log.DebugFormat("Table {0} is cached.",tableName);
     }
    }
    catch (Exception ex)
    {
     result = query.Context.GetTable<T>().ToList();
     HttpContext.Current.Cache.Insert(tableName,result);

     string msg = string.Format(CultureInfo.InvariantCulture,"Table {0} is cached without sqlCacheDependency!!!",tableName);

     _Log.Warn(msg,ex);
    }
            }
            return result;
        }
    }

c# – SqlDependency简单选择查询总是返回“无效”

c# – SqlDependency简单选择查询总是返回“无效”

我正在尝试让sqlDependency对象给我通知,但到目前为止我无法让它工作.

我发送的SQL查询是这样的:

SELECT [SocialMedia].[dbo].[Items].[Id]
  FROM [SocialMedia].[dbo].[Items]

我已经尝试了w /和没有大括号,具有完全限定名称,只有变量名称,以及中间的所有内容.

Id是Guid类型,我没有看到它们在Creating a Query for Notification文章中没有使用sqlDependency对象

我也试过发送多个列来查看是否可行.

SELECT SocialMedia.dbo.Items.Id,SocialMedia.dbo.Items.DateTimeCreated,SocialMedia.dbo.Items.AuthorId
  FROM   SocialMedia.dbo.Items

这也没有用.

这是我的表sql:

USE [SocialMedia]

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
SET ANSI_PADDING ON

CREATE TABLE [dbo].[Items](
    [Id] [uniqueidentifier] NOT NULL,[DateTimeCreated] [datetimeoffset](7) NOT NULL,[AuthorId] [uniqueidentifier] NOT NULL,[Source] [varchar](max) NOT NULL,[PlaceId] [uniqueidentifier] NULL,[FullText] [varchar](max) NOT NULL,[Geography] [geography] NULL,[DateTimeAdded] [datetime] NULL,CONSTRAINT [PK_Items] PRIMARY KEY CLUSTERED ( [Id] ASC ) 
                 WITH (PAD_INDEX = OFF,STATISTICS_norECOmpuTE = OFF,IGnorE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXtimage_ON [PRIMARY]

GO

ALTER TABLE [dbo].[Items]  WITH CHECK ADD  CONSTRAINT [FK_Items_Places] 
FOREIGN KEY([PlaceId]) REFERENCES [dbo].[Places] ([Id])

ALTER TABLE [dbo].[Items] CHECK CONSTRAINT [FK_Items_Places]

GO
ALTER TABLE [dbo].[Items]  WITH CHECK ADD  CONSTRAINT [FK_Items_Users] 
FOREIGN KEY([AuthorId]) REFERENCES [dbo].[Users] ([Id])

ALTER TABLE [dbo].[Items] CHECK CONSTRAINT [FK_Items_Users]

我的DB:

USE [master]
GO

CREATE DATABASE [SocialMedia]
 CONTAINMENT = NONE
 ON  PRIMARY 
 ( NAME = N'SocialMedia',FILENAME = N'C:\Program Files\Microsoft sql Server\MSsql11.DENALI\MSsql\DATA\SocialMedia.mdf',SIZE = 1110016KB,MAXSIZE = UNLIMITED,FILEGROWTH = 1024KB )
 LOG ON 
( NAME = N'SocialMedia_log',FILENAME = N'C:\Program Files\Microsoft sql Server\MSsql11.DENALI\MSsql\DATA\SocialMedia_log.ldf',SIZE = 123648KB,MAXSIZE = 2048GB,FILEGROWTH = 10%)
GO

ALTER DATABASE [SocialMedia] SET COMPATIBILITY_LEVEL = 110
GO

IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled')) BEGIN
  EXEC [SocialMedia].[dbo].[sp_fulltext_database] @action = 'enable'
END
GO

ALTER DATABASE [SocialMedia] SET ANSI_NULL_DEFAULT OFF 
ALTER DATABASE [SocialMedia] SET ANSI_NULLS ON 
ALTER DATABASE [SocialMedia] SET ANSI_PADDING ON 
ALTER DATABASE [SocialMedia] SET ANSI_WARNINGS ON 
ALTER DATABASE [SocialMedia] SET ARITHABORT ON 
ALTER DATABASE [SocialMedia] SET AUTO_CLOSE OFF 
ALTER DATABASE [SocialMedia] SET AUTO_CREATE_STATISTICS ON 
ALTER DATABASE [SocialMedia] SET AUTO_SHRINK OFF 
ALTER DATABASE [SocialMedia] SET AUTO_UPDATE_STATISTICS ON 
ALTER DATABASE [SocialMedia] SET CURSOR_CLOSE_ON_COMMIT OFF 
ALTER DATABASE [SocialMedia] SET CURSOR_DEFAULT  GLOBAL 
ALTER DATABASE [SocialMedia] SET CONCAT_NULL_YIELDS_NULL ON 
ALTER DATABASE [SocialMedia] SET NUMERIC_ROUNDABORT OFF 
ALTER DATABASE [SocialMedia] SET QUOTED_IDENTIFIER ON 
ALTER DATABASE [SocialMedia] SET RECURSIVE_TRIGGERS OFF 
ALTER DATABASE [SocialMedia] SET  ENABLE_broKER 
ALTER DATABASE [SocialMedia] SET AUTO_UPDATE_STATISTICS_ASYNC OFF 
ALTER DATABASE [SocialMedia] SET DATE_CORRELATION_OPTIMIZATION OFF 
ALTER DATABASE [SocialMedia] SET TRUSTWORTHY OFF 
ALTER DATABASE [SocialMedia] SET ALLOW_SNAPSHOT_ISOLATION OFF 
ALTER DATABASE [SocialMedia] SET ParaMETERIZATION SIMPLE 
ALTER DATABASE [SocialMedia] SET READ_COMMITTED_SNAPSHOT OFF 
ALTER DATABASE [SocialMedia] SET HOnor_broKER_PRIORITY OFF 
ALTER DATABASE [SocialMedia] SET RECOVERY FULL 
ALTER DATABASE [SocialMedia] SET  MULTI_USER 
ALTER DATABASE [SocialMedia] SET PAGE_VERIFY CHECKSUM  
ALTER DATABASE [SocialMedia] SET DB_CHAINING OFF 
ALTER DATABASE [SocialMedia] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF ) 
ALTER DATABASE [SocialMedia] SET TARGET_RECOVERY_TIME = 0 SECONDS 
ALTER DATABASE [SocialMedia] SET  READ_WRITE

我用来运行它的代码:

string connString = ConfigurationManager.ConnectionStrings["applicationservices"].ConnectionString;
conn = new sqlConnection(connString);
conn.open(); // open new connection and create command to notify about all new Chat-Messages in -ROOM_NUMBER- const
using (var sqlCommand = new sqlCommand(GetSearchQueryString(searchItems),conn))
{
    var sqlDependency = new sqlDependency(sqlCommand
    //handle onChange event - this will be fired whenever there is a change in database that affacts our query
    sqlDependency.OnChange += (sender,e) =>
    {
        //change detected - get all messages...
        try
        {

            var sql = GetSearchQueryString(searchItems);
            int count = _entities.ExecuteStoreQuery<Guid>(sql).Count();

            AsyncManager.Parameters["count"] = count;
        }
        finally
        {
            AsyncManager.OutstandingOperations.Decrement();
        }
    };
    sqlCommand.ExecuteNonQuery();
}

我正在调用sqlDependency.Start(ConfigurationManager.ConnectionStrings [“applicationservices”].ConnectionString);在该计划的早期.

我错过了什么吗?我觉得我错过了一些明显的东西……

解决方法

我们按照 http://dimarzionist.wordpress.com/2009/04/01/how-to-make-sql-server-notifications-work/中描述的步骤进行操作

c# – 使用SqlDependency导致不断更新

c# – 使用SqlDependency导致不断更新

我从 this MSDN page中提取了一个例子并且几乎逐字地使用了它.运行时代码编译正确,但无论是否实际对返回的数据进行了更改,changeCount都会无限增加.实际发生更改时,dataGridView1会正确反映更改.为什么我的sqlDependency看起来像是在循环中触发,即使显然没有变化?

这是来源:

#region Using directives
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.sqlClient;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Text;
using System.Windows.Forms;
#endregion

namespace PreAllocation_Check
{
    public partial class Form1 : Form
    {
        int           changeCount = 0;
        const string  tableName = "MoxyPosition";
        const string  statusMessage = "Last: {0} - {1} changes.";
        DataSet       dataToWatch = null;
        sqlConnection MoxyConn = null;
        sqlCommand    sqlComm = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender,EventArgs e)
        {
            if (CanRequestNotifications())
            {
                sqlDependency.Start(GetConnectionString());

                if (MoxyConn == null)
                    MoxyConn = new sqlConnection(GetConnectionString());

                if (sqlComm == null)
                {
                    sqlComm = new sqlCommand(Getsql(),MoxyConn);

                    sqlParameter prm = new sqlParameter("@Quantity",sqlDbType.Int);
                    prm.Direction = ParameterDirection.Input;
                    prm.DbType = DbType.Int32;
                    prm.Value = 100;
                    sqlComm.Parameters.Add(prm);
                }

                if (dataToWatch == null)
                    dataToWatch = new DataSet();

                GetData();
            }
        }

        private void Form1_FormClosed(object sender,FormClosedEventArgs e)
        {
            sqlDependency.Stop(GetConnectionString());
            if (MoxyConn != null)
                MoxyConn.Close();
        }

        private bool CanRequestNotifications()
        {
            try
            {
                sqlClientPermission sqlPerm = new sqlClientPermission(PermissionState.Unrestricted);
                sqlPerm.Demand();
                return true;
            }
            catch
            {
                return false;
            }
        }

        private string GetConnectionString()
        {
            return "server=***;database=***;user id=***;password=***";
        }

        private void GetData()
        {
            dataToWatch.Clear();
            sqlComm.Notification = null;
            sqlDependency sqlDep = new sqlDependency(sqlComm);
            sqlDep.OnChange += new OnChangeEventHandler(sqlDep_OnChange);

            using (sqlDataAdapter adapter = new sqlDataAdapter(sqlComm))
            {
                adapter.Fill(dataToWatch,tableName);
                dataGridView1.DataSource = dataToWatch;
                dataGridView1.DataMember = tableName;
            }
        }

        private string Getsql()
        {
            return "SELECT PortID,CONVERT(money,SUM(PreAllocPos),1) AS PreAllocation,SUM(AllocPos),1) AS Allocation,SUM(PreAllocPos) - SUM(AllocPos),1) AS PreLessAlloc " +
                   "FROM MoxyPosition " +
                   "WHERE CONVERT(money,PreAllocPos,1) <> CONVERT(money,AllocPos,1) " +
                   "GROUP BY PortID " +
                   "ORDER BY PortID ASC;";
        }

        void sqlDep_OnChange(object sender,sqlNotificationEventArgs e)
        {
            isynchronizeInvoke i = (isynchronizeInvoke)this;

            if (i.Invokerequired)
            {
                OnChangeEventHandler tempDelegate = new OnChangeEventHandler(sqlDep_OnChange);
                object[] args = { sender,e };
                i.BeginInvoke(tempDelegate,args);
                return;
            }

            sqlDependency sqlDep = (sqlDependency)sender;
            sqlDep.OnChange -= sqlDep_OnChange;

            changeCount++;
            DateTime LastRefresh = System.DateTime.Now;
            label1.Text = String.Format(statusMessage,LastRefresh.TimeOfDay,changeCount);

            GetData();
        }
    }
}

编辑:值得注意的是,我想要运行此数据库的数据库当前没有启用broker服务,因此要测试我的代码我备份了我的目标数据库并使用新名称恢复它,然后运行ALTER DATABASE my_db_name SET ENABLE_broKER反对.我的所有测试都在这个备用数据库上,这意味着我是唯一的用户.

解决方法

这是一个老问题,但问题是您的查询不符合要求.

简短回答:
将模式名称添加到表“FROM DBO.MoxyPosition”

更长的答案:
您可以看到list of requirements here,这与创建索引视图非常相似.注册sql依赖项时,如果它无效,通知会立即触发,让您知道它无效.当你考虑它时,这是有道理的,因为Visual Studio如何知道sql Engine的内部要求是什么?

因此,在sqlDep_OnChange函数中,您将要查看依赖项触发的原因.原因在于e变量(info,source和type).有关事件对象的详细信息,请访问:

> Info options
> Source
> Type

针对您的具体情况,请注意MS describes的Type属性:

Gets a value that indicates whether this notification is generated 
because of an actual change,OR BY THE SUBSCRIPTION.

我们今天的关于SQLDependency +服务代理sql server 代理服务的分享就到这里,谢谢您的阅读,如果想了解更多关于.NET 2.0 SqlDependency 快速上手指南、asp.net中的SqlDependency、c# – SqlDependency简单选择查询总是返回“无效”、c# – 使用SqlDependency导致不断更新的相关信息,可以在本站进行搜索。

本文标签: