本文的目的是介绍SQLDependency+服务代理的详细情况,特别关注sqlserver代理服务的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解SQLDepende
本文的目的是介绍SQLDependency +服务代理的详细情况,特别关注sql server 代理服务的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解SQLDependency +服务代理的机会,同时也不会遗漏关于.NET 2.0 SqlDependency 快速上手指南、asp.net中的SqlDependency、c# – SqlDependency简单选择查询总是返回“无效”、c# – 使用SqlDependency导致不断更新的知识。
本文目录一览:- SQLDependency +服务代理(sql server 代理服务)
- .NET 2.0 SqlDependency 快速上手指南
- asp.net中的SqlDependency
- c# – SqlDependency简单选择查询总是返回“无效”
- c# – 使用SqlDependency导致不断更新
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 快速上手指南
此文以 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
我应该为每个代码创建这样的代码:
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(); }
或者我可以在它们之间重复使用它喜欢连接?
这是设置多个通知的首选方式吗?
解决方法
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简单选择查询总是返回“无效”
我发送的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);在该计划的早期.
我错过了什么吗?我觉得我错过了一些明显的东西……
解决方法
c# – 使用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导致不断更新的相关信息,可以在本站进行搜索。
本文标签: