首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我的SqlDependency订阅有一个“开放数据阅读器”例外?

为什么我的SqlDependency订阅有一个“开放数据阅读器”例外?
EN

Stack Overflow用户
提问于 2013-11-27 05:02:48
回答 2查看 392关注 0票数 0

最后,我收集了大量功能异常的示例,终于成功地在SqlDependency对象上接收到了更改消息。这些知识可能会使您为我的代码的不优雅或明显的不正确做好准备。

我有一个ActiveList<T>: ObservableCollection<T>类,它侦听对其DB表数据源的更改并重新填充自身。我使用以下代码来创建和初始化列表和SqlDependency

构造者:

代码语言:javascript
复制
public ActiveList()
{
    PopulateList();
}

人口:

代码语言:javascript
复制
private void PopulateList()
{        Application.Current.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, ((Action)(() =>
    {
        Clear();
        using (var dbContext = new XTimeDbContext())
        {
            var set = dbContext.Set<T>().ToList();
            this.AddRange(set);
        }
    })));
    SubscribeNotifications();
}

订阅:

代码语言:javascript
复制
private void SubscribeNotifications()
{
    const string dependencyQuery = "select TITLE_ACTIVE, TITLE_NAME from dbo.TITLE";
    var dependency = new SqlDependency();
    dependency.OnChange += DependencyOnChange;
    var connectionString = _dbContext.Database.Connection.ConnectionString;

    //SqlDependency.Stop(connectionString);
    SqlDependency.Start(connectionString);
    using (var sqn = new SqlConnection(connectionString))
    {
        sqn.Open();
        using (var cmd = new SqlCommand(dependencyQuery, sqn))
        {
            cmd.Notification = null;
            dependency.AddCommandDependency(cmd);
            //dependency.OnChange += DependencyOnChange;
            using (var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
            {
                while (reader.Read())
                {
                }
            }                
        }
    }
}

最后,听着:

代码语言:javascript
复制
private void DependencyOnChange(object sender, SqlNotificationEventArgs sqlNotificationEventArgs)
{
    _trace.TraceInformation("DependencyOnChange called. Reason: '{0}', Source: '{1}', Type: '{2}'.", sqlNotificationEventArgs.Info, sqlNotificationEventArgs.Source,
        sqlNotificationEventArgs.Type);
    //if (!_isPopulating)
    //{
    //    PopulateList();
    //}
    SqlDependency.Stop(_dbContext.Database.Connection.ConnectionString;);
    SubscribeNotifications();
    _trace.TraceInformation("DependencyOnChange completed.");
}

由于大量小的实验性更改,代码略有混乱,但我的主要问题是,当我运行使用ActiveList的测试应用程序时,我收到了第一个更改通知;我的日志显示了"DependencyOnChange调用“。然后,对SqlDependency.Stop的调用(无论我放置它的位置)生成一个InvalidOperationException,其中包含以下消息:

代码语言:javascript
复制
There is already an open DataReader associated with this Command which must be closed first.

我在代码中任何地方都找不到“悬空”DataReaders,那么是什么原因造成了这种情况呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-28 08:30:10

您应该在开始时只调用SqlDependency.Start(connectionString);一次,在结束时只调用SqlDependency.Stop(_dbContext.Database.Connection.ConnectionString;);一次(当您决定不跟踪更改时)。这些命令为更改事件创建和删除队列。

当您需要订阅下一个更改时,您应该调用下一行。

代码语言:javascript
复制
var dependency = new SqlDependency();
dependency.OnChange += DependencyOnChange;

特别代表:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            SqlDependency.Start("server=<MyServer>;database=<MyDB>;User ID=<user>;Password=<pwd>;Integrated Security=false;");
            Console.WriteLine("Started..");
            get_msg();
            Console.ReadLine();
            SqlDependency.Stop("server=<MyServer>;database=<MyDB>;User ID=<user>;Password=<pwd>;Integrated Security=false;");
        }
        private static void get_msg()
        {
            using (SqlConnection con =
                            new SqlConnection("server=<MyServer>;database=<MyDB>;User ID=<user>;Password=<pwd>;Integrated Security=false;"))
            {
                SqlCommand com = new SqlCommand("SELECT MyTableID, SomeText FROM dbo.MyTable ", con);
                SqlDependency dependency = new SqlDependency(com);
                dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
                con.Open();
                com.ExecuteNonQuery();
            }
        }
        static void dependency_OnChange(object sender, SqlNotificationEventArgs e)
        {
            Console.WriteLine("dependency Info = {0}, time: {1}",e.Info, DateTime.Now);
            get_msg();
        }
    }
}

请记住,SQL依赖关系适用于DB中的更改不频繁的情况。在代码示例中,下一个更改的订阅是即时的,但是等待一段时间是个好主意。

票数 0
EN

Stack Overflow用户

发布于 2013-11-27 10:07:04

也许只是一个解决办法..。但是,您是否尝试在连接上将MultipleActiveResultSets设置为true?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20234287

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档