我目前的情况是,我有一个应用程序需要在新数据到达数据库表时得到通知.数据来自外部源(我无法控制 - 这是唯一的集成选项).当新数据到达时,我的应用程序需要采取某些操作 - 基本上查询新数据,处理它,将结果插入本地表等.
我希望尽可能避免轮询,因为预计数据会实时处理.也就是说,确保没有数据丢失是第一优先级.
我的问题:
我使用表作为消息队列,并使用SqlDependency"注册"以获取更新.我读到的每个地方的人都在说要注意它的局限性,但没有具体说明它们是什么.从我收集的内容来看,当表具有非常高的更新频率时,你会遇到问题,幸运的是我只看到每分钟最多10-20个值.
对SqlServer有哪些其他限制/影响?
我已经在.NET 3.5应用程序中使用SqlDependency超过3年没有任何问题.方案如下:
最近我将系统升级到.NET 4.5,并开始看到将更改放入我们正在监视的表中的问题,但SqlDependency永远不会触发(在服务和用户应用程序中).我开始深入研究这一点,并在我的日志中注意到,在某些时候我会重新注册SqlDependency,但之后通知永远不会触发.
看到此行为后,我决定在SQL Server上运行探查器来捕获订阅事件.从捕获的数据中,我注意到有时订阅将由一个用户注册(具有唯一ID),但随后将由另一个用户触发(具有相同的唯一ID).这通常发生在我上面提到的服务和WPF应用程序的一个或多个用户身上.(我在分析器结果中附上了该问题的屏幕截图)
这是预期的行为吗?是否可以针对不同的用户触发通知?这是否指向应用程序层中的问题?任何帮助表示赞赏.
我正在使用SqlDependency类,并且一直尝试找不到SqlNotificationEventArgs对象的Type,Source和Info属性的可能组合列表.
这是迄今为止我发现的最接近的.但是,我知道这并不能涵盖所有内容,因为我已经看到了组合Change/Client/Error.
我真的很想知道我是否以最好的方式处理所有可能的情况.也就是说,只要有可能,我想重新建立"订阅".
例如,更改/客户端/错误是针对网络问题,该问题中断了SqlServer与我的应用之间的通信.一旦重新建立通信,我就能够成功恢复.
如果我举一些关于我所担心的例子,也许会有所帮助.对于我说"恢复"时的以下问题,我的意思是在运行时重新建立订阅,即无需人工干预.
我正在使用SQLDependency来通知我数据库是否有变化.程序启动后,它工作得很好.当我进行第一次更改时,事件会触发.Wohoo ......太好了.但如果我做了第二次更改,事件就不再发生了.我搜索了所有网络,但我没有发现任何有关此问题的信息.仅发现OnChange-Event在循环中触发的问题.谁能帮我?
这里有一小段代码:
private void GetStates()
{
if (!DoesUserHavePermission())
return;
SqlDependency.Stop(con);
SqlDependency.Start(con);
using (SqlConnection cn = new SqlConnection(con))
{
using (SqlCommand cmd = cn.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT Bla, Bla2, ..FROM dbo.[BLA3]"
cmd.Notification = null;
cmd.Dispose();
SqlDependency dep = new SqlDependency(cmd);
dep.OnChange += new OnChangeEventHandler(dep_OnChange);
cn.Open();
using (SqlDataReader dr = cmd.ExecuteReader())
{
state.Clear(); //In this Case "state" is a List<string>
while (dr.Read())
{
state.Add(dr.GetString(0) + "|" + dr.GetInt32(3));
}
dr.Dispose();
dr.Close();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的OnChange-Event看起来像这样:
private …Run Code Online (Sandbox Code Playgroud) 我开发这个应用程序VB.net 2010和SQL 2008.
我希望通知客户端有关db的更新,以及用于使用计时器检查db在指定分钟内的更改的应用程序,这实际上效率不高.我读到query notification,sqldependency,service broker,但后来我读到的东西,说他们可能不是有效的,如果我有100个客户,我使用查询通知推送通知我的申请.
有人会帮我解决我应该做的事情,以及如何做到这一点(如果可以提供示例,将会非常有用).提前致谢!
sql-server service-broker push-notification sqldependency query-notifications
在我们的应用程序开发之初,我们非常重视SQLDependency来缓存数据库结果,直到通知告诉我们的应用程序获取新副本.
在测试期间,我们注意到sql db的性能受到sqldependency通知服务的影响.我们缩减了使用sqldependency的表的数量,并注意到性能的大幅提升.所以,我们认为我们刚刚过度使用它,我们继续前进.我们现在只有几张桌子.
后来我们发现我们无法缩减将建立依赖关系的用户名的安全访问级别.我们可以为每个db创建多个连接字符串(一个用于依赖,一个用于应用程序的其余部分)但是有多个db和db镜像,这很痛苦(从sql db管理角度和应用程序开发)
在这一点上,我们只是考虑基于以下逻辑完全脱离SQLDependency:
有没有人看到这个逻辑的缺陷?
每秒轮询一个表会导致数据库上的负载比SQLDependency更多或更少吗?
是否有人与SQLDependency有类似的性能问题?
我试图让System.Runtime.Caching命名空间中包含的新SqlChangeMonitor功能工作,并得到一些意想不到的结果.
我有一个简单的控制台应用程序设置为:
static void Main(string[] args)
{
var cacher = new Cacher();
cacher.Start();
Console.WriteLine("Watching for changes...");
while (true)
{
if (cacher.HasData)
{
Console.Write(".");
Thread.Sleep(1000);
}
else
{
Console.WriteLine();
Console.WriteLine("Cache EMPTY!");
Console.ReadLine();
cacher.Start();
}
}
}
Run Code Online (Sandbox Code Playgroud)
Cacher类定义为:
public class Cacher
{
private MemoryCache cache = new MemoryCache("test");
public Boolean HasData
{
get { return cache.Contains("data"); }
}
public void Start()
{
var connectionString = "Data Source=.;Initial Catalog=CachingTest;Integrated Security=True";
var list = new NameValueCollection();
var policy = new CacheItemPolicy();
SqlDependency.Start(connectionString);
using (var …Run Code Online (Sandbox Code Playgroud) 如何清理SQL Server以清除过期的SqlDependency对象?从SqlDepedency对象收到事件后,我需要创建一个新事件才能获得新事件.但是,SQL Server进程的内存使用量会增加,直到超出允许的内存(SQL Server Express).如何摆脱旧查询?
码:
// Func: RegisterTableListener
using (SqlConnection cn = new SqlConnection(Properties.Settings.Default.DatabseEventConnectionString))
{
if (cmd == null)
{
cmd = cn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT HostName, LastStatus, LastDetails, xml FROM dbo.[SystemTable]";
}
lock (cmd)
{
cmd.Connection = cn;
cn.Open();
cmd.Notification = null;
// creates a new dependency for the SqlCommand
if (dep == null)
dep = new SqlDependency(cmd);
// creates an event handler for the notification of data
// changes in …Run Code Online (Sandbox Code Playgroud) 我正在使用EF 6 async查询功能,例如
var list = await cx.Clients.Where(c => c.FirstName.Length > 0).ToListAsync();
Run Code Online (Sandbox Code Playgroud)
我还想在这些查询上启动SQL依赖项,以便在数据库中的数据发生更改时收到通知.我可以使用System.Runtime.Remoting.Messaging.CallContext以下内容执行此操作:
async Task GetData()
{
using (ClientsContext context = new ClientsContext()) // subclass of DbContext
{
SqlDependency.Start(context.Database.Connection.ConnectionString);
SqlDependency dependency = new SqlDependency();
dependency.OnChange += (sender, e) =>
{
Console.Write(e.ToString());
};
System.Runtime.Remoting.Messaging.CallContext.SetData("MS.SqlDependencyCookie", dependency.Id);
var list = await context.Clients.Where(c => c.FirstName.Length > 0).ToListAsync();
}
}
Run Code Online (Sandbox Code Playgroud)
..它工作正常.但是,如果我想要一个SqlDependency多个查询,我遇到了一个问题.如果我有两个async类似于GetData()上面的方法,并且我同时运行两个方法,则只有第一个方法会获得更改通知.我假设这是由于CallContext连续地为每个方法设置了cookie.如果我等待第一个async方法完成,然后调用第二个方法,它们都会按预期获得更改通知.这有什么解决方案吗?
sqldependency ×10
c# ×8
sql-server ×3
.net ×1
.net-4.5 ×1
asynchronous ×1
caching ×1
sql ×1
wpf ×1