读取SQL Server代理消息并使用NServiceBus发布它们

读取SQL Server代理消息并使用NServiceBus发布它们,nservicebus,Nservicebus,我对NServiceBus非常陌生,在我们的一个项目中,我们希望实现以下目标- 每当在Sql server中修改表数据时,构造一条消息并插入Sql server代理队列 使用NServiceBus读取代理队列消息 将消息作为另一个事件再次发布,以便其他订阅者 我能应付 现在是第二点,我没有太多的线索,如何完成它 我参考了以下文章,之后我可以在代理队列中输入消息,但无法在我们的项目中与NServiceBus集成,因为NServiceBus库的版本较旧,而且使用的许多方法也不推荐。所以在当前版本中使

我对NServiceBus非常陌生,在我们的一个项目中,我们希望实现以下目标-

  • 每当在Sql server中修改表数据时,构造一条消息并插入Sql server代理队列
  • 使用NServiceBus读取代理队列消息
  • 将消息作为另一个事件再次发布,以便其他订阅者 我能应付
  • 现在是第二点,我没有太多的线索,如何完成它

    我参考了以下文章,之后我可以在代理队列中输入消息,但无法在我们的项目中与NServiceBus集成,因为NServiceBus库的版本较旧,而且使用的许多方法也不推荐。所以在当前版本中使用它们会变得非常麻烦,或者如果我使用的方式不正确的话

    在正确方法上的任何帮助都是无价的


    谢谢。

    据我记忆所及,ServiceBroker传输非常旧,不再受支持。 一个可能的解决方案是使用类似SqlDependency()的东西从端点代码“监视”感兴趣的表,然后将消息推送到相关队列中


    .m

    我使用的是nServiceBus(5)、VS2013和SQL Server 2008的当前版本。我使用创建了一个数据库更改侦听器,它使用SQLServer对象代理和SQLDependency来监视对特定表的更改。(注意,在SQL Server的更高版本中,这可能会被弃用)

    SQL依赖关系允许您使用所有基本SQL功能的广泛选择,尽管有一些需要注意的功能。我稍微修改了教程中的代码,以提供更好的错误信息:

        void NotifyOnChange(object sender, SqlNotificationEventArgs e)
        {
            // Check for any errors
            if (@"Subscribe|Unknown".Contains(e.Type.ToString())) { throw _DisplayErrorDetails(e); }
    
            var dependency = sender as SqlDependency;
            if (dependency != null) dependency.OnChange -= NotifyOnChange;
            if (OnChange != null) { OnChange(); }
        }
    
        private Exception _DisplayErrorDetails(SqlNotificationEventArgs e)
        {
            var message = "useful error info";
    
            var messageInner = string.Format("Type:{0}, Source:{1}, Info:{2}", e.Type.ToString(), e.Source.ToString(), e.Info.ToString());
    
            if (@"Subscribe".Contains(e.Type.ToString()) && @"Invalid".Contains(e.Info.ToString()))
                messageInner += "\r\n\nThe subscriber says that the statement is invalid - check your SQL statement conforms to specified requirements (http://stackoverflow.com/questions/7588572/what-are-the-limitations-of-sqldependency/7588660#7588660).\n\n";
    
            return new Exception(messageMain, new Exception(messageInner));
    
        }
    
    我还创建了一个具有“数据库优先”实体框架数据模型的项目,以允许我处理更改后的数据

    我的nServiceBus项目的[相关部分]包括两个“作为主机运行”端点,其中一个端点发布事件消息。第二个端点处理消息。发布服务器已设置为IWantToRunAtStartup,它实例化DBListener,并将我希望作为更改监视器运行的SQL语句传递给它。onChange()函数通过一个匿名函数读取更改的数据并发布消息:

    using statements
    
    namespace Sample4.TestItemRequest
    {
        public partial class MyExampleSender : IWantToRunWhenBusStartsAndStops
        {
            private string NOTIFY_SQL = @"SELECT [id] FROM [dbo].[Test] WITH(NOLOCK) WHERE ISNULL([Status], 'N') = 'N'";
        public void Start() { _StartListening(); }
        public void Stop() { throw new NotImplementedException(); }
    
        private void _StartListening()
        {
            var db = new Models.TestEntities();
    
            // Instantiate a new DBListener with the specified connection string            
            var changeListener = new DatabaseChangeListener(ConfigurationManager.ConnectionStrings["TestConnection"].ConnectionString);
    
            // Assign the code within the braces to the DBListener's onChange event
            changeListener.OnChange += () =>
            {
                /* START OF EVENT HANDLING CODE  */
    
                //This uses LINQ against the EF data model to get the changed records
                IEnumerable<Models.TestItems> _NewTestItems = DataAccessLibrary.GetInitialDataSet(db);
    
                while (_NewTestItems.Count() > 0)
                {
                    foreach (var qq in _NewTestItems)
                    {
                        // Do some processing, if required
    
                        var newTestItem = new NewTestStarted() { ... set properties from qq object ... };
                        Bus.Publish(newTestItem);
                    }
    
                    // Because there might be a number of new rows added, I grab them in small batches until finished.
                    // Probably better to use RX to do this, but this will do for proof of concept
                    _NewTestItems = DataAccessLibrary.GetNextDataChunk(db);
    
                }
    
                changeListener.Start(string.Format(NOTIFY_SQL));
    
                /* END OF EVENT HANDLING CODE  */
    
            };
    
            // Now everything has been set up.... start it running.
            changeListener.Start(string.Format(NOTIFY_SQL));
    
            }
        }
    }
    
    使用语句
    命名空间Sample4.TestItemRequest
    {
    公共部分类MyExampleSsender:Iwanttorunshenbus开始和停止
    {
    私有字符串NOTIFY_SQL=@“使用(NOLOCK)从[dbo].[Test]中选择[id],其中ISNULL([Status],'N')='N';
    public void Start(){u StartListening();}
    public void Stop(){抛出新的NotImplementedException();}
    私有无效
    {
    var db=新模型.TestEntities();
    //使用指定的连接字符串实例化新的DBListener
    var changeListener=新数据库changeListener(ConfigurationManager.ConnectionString[“TestConnection”].ConnectionString);
    //将大括号内的代码分配给DBListener的onChange事件
    changeListener.OnChange+=()=>
    {
    /*事件处理代码的开始*/
    //这对EF数据模型使用LINQ来获取更改的记录
    IEnumerable _NewTestItems=DataAccessLibrary.GetInitialDataSet(db);
    而(_NewTestItems.Count()>0)
    {
    foreach(新测试中的变量qq)
    {
    //如果需要,进行一些处理
    var newtesttem=new NewTestStarted(){…从qq对象设置属性…};
    发布(新测试项目);
    }
    //因为可能会添加许多新行,所以我将以小批量方式获取它们,直到完成。
    //也许最好使用RX来实现这一点,但这将用于概念验证
    _NewTestItems=DataAccessLibrary.GetNextDataChunk(db);
    }
    changeListener.Start(string.Format(NOTIFY_SQL));
    /*事件处理代码结束*/
    };
    //现在一切都已设置好…开始运行。
    changeListener.Start(string.Format(NOTIFY_SQL));
    }
    }
    }
    
    重要OnChange事件触发会导致侦听器停止监视。它基本上是一个单事件通知程序。处理完事件后,要做的最后一件事是重新启动DBListener。(您可以在事件处理注释结尾前的一行中看到这一点)

    您需要添加对System.Data和System.Data.DataSetExtensions的引用

    目前这个项目仍然是概念验证,所以我很清楚上面的内容可以有所改进。还要记住,我必须去掉公司特定的代码,所以可能会有bug。将其视为模板,而不是工作示例

    我也不知道这是否是放置代码的正确位置-这就是我今天在StackOverflow上的部分原因;寻找更好的ServiceBus主机代码示例。无论我的代码有什么缺陷,到目前为止,解决方案都非常有效,并且也满足了您的目标


    不要太担心ServiceBroker方面的事情。一旦您设置好它,根据教程,SQLDependency会为您处理细节。

    只有一件小事:删除Stop方法实现中的NotImplementedException,否则每次启动时端点都会崩溃shutdown@Mauro-当您“实现接口”时,VS会自动将其添加。我在为发布清理代码时没有注意到这一点,它可能仍在我的代码中,因为它仍在开发/测试中。谢谢你来接我;我会忘记的,它会咬我的@AnyoneStillReading此-my NOTIFY_SQL中的WITH(NOLOCK)与SQLDependency不兼容。我认为这是从一个初始的测试版本,我已经更新。这