与EntityFramework 6的SqlDependency(异步)

时间:2013-06-27 05:07:55

标签: c# entity-framework asynchronous sqldependency

我正在使用EF 6 async查询功能,例如

var list = await cx.Clients.Where(c => c.FirstName.Length > 0).ToListAsync();

我还想在这些查询上启动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();
        }
    }

..它工作正常。但是如果我想在多个查询上使用SqlDependency,我会遇到问题。如果我有两个类似于async的{​​{1}}方法,并且我同时运行两个方法,则只有第一个方法会获得更改通知。我假设这是由于CallContext连续地为每个方法设置了cookie。如果我等待第一个GetData()方法完成,然后调用第二个,它们都会按预期获得更改通知。这有什么解决方案吗?

1 个答案:

答案 0 :(得分:9)

我对SqlDependency不太熟悉,但是下面的内容将允许您的CallContext在调用ToListAsync时具有正确的值(当多个调用正在运行时)。这里的概念证明,https://dotnetfiddle.net/F8FnFe

    async Task<List<Client>> 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());
            };

            Task<List<Client>> task = Task<Task<List<Client>>>.Factory.StartNew(async () =>
            {
                System.Runtime.Remoting.Messaging.CallContext.SetData("MS.SqlDependencyCookie", dependency.Id);
                var list = await context.Clients.Where(c => c.FirstName.Length > 0).ToListAsync();
            }).Unwrap();

            return await task;
        }
    }