我正在监视数据库表以进行数据更改,例如insert / Update。一些sql依赖项抛出错误我听说就像3/4天这样长时间没有特定表的活动。我试图说,如果我正在监视一个表,如果该表中没有插入或更新数据很长时间,那么SQL依赖关系抛出错误。 这是我的代码。请查看我的代码并告诉我正确处理错误。
我的sql依赖代码是用windows服务编写的。我想如果抛出任何错误,那么我的Windows服务应该重新启动。这是我的完整代码
public partial class PartIndexer : ServiceBase
{
static string connectionString = "server=222;uid=222;password=222;database=wwww;Pooling=true;Connect Timeout=20;";
SqlDependency dep;
public PartIndexer()
{
InitializeComponent();
}
#region OnStart
protected override void OnStart(string[] args)
{
RegisterNotification();
MailNotify("STARTED");
}
#endregion
#region RegisterNotification
/// <summary>
/// RegisterNotification
/// this is main routine which will monitor data change in ContentChangeLog table
/// </summary>
private void RegisterNotification()
{
string tmpdata = "";
System.Data.SqlClient.SqlDependency.Stop(connectionString);
System.Data.SqlClient.SqlDependency.Start(connectionString);
try
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT ActivityDate FROM [bba-reman].MyLog";
dep = new SqlDependency(cmd);
dep.OnChange += new OnChangeEventHandler(OnDataChange);
SqlDataReader dr = cmd.ExecuteReader();
{
while (dr.Read())
{
if (dr[0] != DBNull.Value)
{
tmpdata = dr[0].ToString();
}
}
}
dr.Dispose();
cmd.Dispose();
}
}
finally
{
//SqlDependency.Stop(connStr);
}
}
#endregion
// this below function never used
public void ReStartService()
{
ServiceController service = new ServiceController("PartIndexer");
if ((service.Status.Equals(ServiceControllerStatus.Stopped)) || (service.Status.Equals(ServiceControllerStatus.StopPending)))
{
service.Start();
}
else
{
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped);
service.Start();
service.WaitForStatus(ServiceControllerStatus.Running);
}
}
#region OnDataChange
/// <summary>
/// OnDataChange
/// OnDataChange will fire when after data change found in ContentChangeLog table
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void OnDataChange(object sender, SqlNotificationEventArgs e)
{
((SqlDependency)sender).OnChange -= OnDataChange;
if (e.Source == SqlNotificationSource.Timeout)
{
var template = new MailTemplate()
.WithBody("HI,<br><br>Part Indexer Service Exception Timeout occur " + DateTime.Now.ToLongDateString())
.WithSubject("Part Indexer Service Exception Timeout occur")
.WithSender("xxx@xxx.com")
.WithRecepient("xxx@xxx.com")
.Send();
Environment.Exit(1);
return;
}
else if (e.Source != SqlNotificationSource.Data)
{
var template = new MailTemplate()
.WithBody("HI,<br><br>Part Indexer Service Exception SqlNotificationSource.Data " + DateTime.Now.ToLongDateString())
.WithSubject("Part Indexer Service Exception SqlNotificationSource.Data")
.WithSender("xxx@xxx.com")
.WithRecepient("xxx@xxx.com")
.Send();
Environment.Exit(1);
}
StartIndex();
RegisterNotification();
}
#endregion
#region StartIndex
/// <summary>
/// StartIndex
/// this routine will call web service in bba reman website which will invoke routine to re-index data
/// </summary>
void StartIndex()
{
//eventLog1.WriteEntry("Web Service called start for indexing data");
PartIndexerWS.AuthHeader oAuth = new PartIndexerWS.AuthHeader();
oAuth.Username = "Admin";
oAuth.Password = "Admin";
PartIndexerWS.SearchDataIndex DataIndex = new PartIndexerWS.SearchDataIndex();
DataIndex.AuthHeaderValue = oAuth;
try
{
DataIndex.StartIndex();
//eventLog1.WriteEntry("Web Service called stop for indexing data");
}
catch (Exception ex)
{
//MessageBox.Show(ex.Message.ToString());
//eventLog1.WriteEntry("Web Service call error "+ex.Message.ToString());
}
}
#endregion
#region MailNotify
/// <summary>
/// MailNotify
/// fire mail when apps start & exit
/// </summary>
/// <param name="strStatus"></param>
void MailNotify(string strStatus)
{
if (strStatus == "STARTED")
{
var template = new MailTemplate()
.WithBody("HI,<br><br>Part Indexer Started Date " + DateTime.Now.ToLongDateString())
.WithSubject("Part Indexer Started")
.WithSender("xxx@xxx.com")
.WithRecepient("xxx@xxx.com")
.Send();
//eventLog1.WriteEntry("mail fired ");
}
else if (strStatus == "STOPPED")
{
var template = new MailTemplate()
.WithBody("HI,<br><br>Part Indexer stopped Date " + DateTime.Now.ToLongDateString())
.WithSubject("Part Indexer Stopped")
.WithSender("xxx@xxx.com")
.WithRecepient("xxx@xxx.com")
.Send();
//eventLog1.WriteEntry("mail fired ");
}
}
#endregion
#region OnStop
protected override void OnStop()
{
System.Data.SqlClient.SqlDependency.Stop(connectionString);
MailNotify("STOPPED");
//eventLog1.WriteEntry("Part Indexer stopped Date : " + DateTime.Now.ToLongDateString());
}
#endregion
}
看到此函数,因为如果发生错误,我将通过此代码Environment.Exit(1);
从此处重新启动服务。
void OnDataChange(object sender, SqlNotificationEventArgs e)
{
((SqlDependency)sender).OnChange -= OnDataChange;
if (e.Source == SqlNotificationSource.Timeout)
{
var template = new MailTemplate()
.WithBody("HI,<br><br>Part Indexer Service Exception Timeout occur " + DateTime.Now.ToLongDateString())
.WithSubject("Part Indexer Service Exception Timeout occur")
.WithSender("xxx@xxx.com")
.WithRecepient("xxx@xxx.com")
.Send();
Environment.Exit(1);
return;
}
else if (e.Source != SqlNotificationSource.Data)
{
var template = new MailTemplate()
.WithBody("HI,<br><br>Part Indexer Service Exception SqlNotificationSource.Data " + DateTime.Now.ToLongDateString())
.WithSubject("Part Indexer Service Exception SqlNotificationSource.Data")
.WithSender("xxx@xxx.com")
.WithRecepient("xxx@xxx.com")
.Send();
Environment.Exit(1);
}
StartIndex();
RegisterNotification();
}
问题是我的服务在特定表中的数据更改时没有发送任何邮件,但是如果我重新启动我的服务,那么当在由sql依赖项监视的特定表中更改数据时,服务正在发送邮件。需要帮助。
答案 0 :(得分:1)
修改强> [删除了关于完全限定表格的评论]
乍一看,您的代码似乎很好。您正在注册该命令并执行它。 我会将其更改为仅执行一次而不是多次执行
注册依赖项后,设置一个断点,然后执行sys.dm_qn_subscriptions
。
如果已注册,请注意status
列,并查看here的含义
如果未注册执行sys.transmission_queue
进行诊断。
这是我订阅的SP备忘单
答案 1 :(得分:1)
小心使用SqlDependency类 - 它有problems内存泄漏。 Hovewer,您可以使用SqlDependency类的开源实现 - SqlDependencyEx。它使用数据库触发器和本机Service Broker通知来接收有关表更改的事件。这是一个用法示例:
int changesReceived = 0;
using (SqlDependencyEx sqlDependency = new SqlDependencyEx(
TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME))
{
sqlDependency.TableChanged += (o, e) => changesReceived++;
sqlDependency.Start();
// Make table changes.
MakeTableInsertDeleteChanges(changesCount);
// Wait a little bit to receive all changes.
Thread.Sleep(1000);
}
Assert.AreEqual(changesCount, changesReceived);
使用SqlDependecyEx,您可以单独监视INSERT,DELETE,UPDATE并在事件args对象中接收实际更改的数据(xml
)。希望这有帮助。