Query Notification ASP.NET-ben

A Query Notification az SQL Server 2005 egyik új szolgáltatása. Ez a szolgáltatás csak az SQL Native Client provider-en keresztül érhető el. lényegében arra jó ez a szolgáltatás, hogy csak akkor frissüljün pl a DataSet a Cache-ben, amikor a mögötte található adat is változik és ne akkor amikor lejár a Cache időkorlátja.

A Query Notification a Service Broker-re épül, ezért azt engedélyezni kell azon az adatbázison, amin szeretnénk használni. Az alábbi kód elvégzi ezt:

1USE [master];
2GO
3 
4IF (SELECT is_broker_enabled FROM sys.databases WHERE [name] = 'AdventureWorks') = 0
5BEGIN
6    ALTER DATABASE AdventureWorks SET ENABLE_BROKER
7END
8GO

Ezek után létre kell hozni egy Queue-t és egy Service-t:

1USE AdventureWorks;
2GO
3CREATE QUEUE QueryNotificationSampleQueue
4GO
5CREATE SERVICE QueryNotificationSampleService ON QUEUE QueryNotificationSampleQueue
6([http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification])
7GO

Ha ezekkel megvagyunk, már csak egy dolog maradt hátra az SQL Serveren.... jogosultság beállitása; a [user] helyére be kell helyettesiteni azt a felhasználót, akinek a nevében csatlakozik az adatbázishoz a webes alaklamazásunk.

1GRANT SUBSCRIBE QUERY NOTIFICATIONS TO [user]

Na innen jön az érdekes rész... kétféleképpen lehet az ASP.NET alkamlazásban ezt beállitani. Most az egyszerűbb megközelitést választom:

Hozzunk létre egy ASP.NET Website-ot a Visual Studio-ban, majd a Default.aspx file-ba a következő kódot másoljuk be:

 1<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default"  %>
 2<%@ OutputCache SqlDependency="CommandNotification" Duration="99999" VaryByParam="none"  %>
 3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 4<html xmlns="http://www.w3.org/1999/xhtml">
 5    <head runat="server">
 6    <title>SQL Query Notification Sample</title> 7
 7    </head>
 8    <body>
 9        <form id="form1" runat="server">
10            <div>
11                <asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1">
12                </asp:GridView>
13                <asp:SqlDataSource ID="SqlDataSource1" runat="server"
14                                    ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>"
15                                    SelectCommand="SELECT [CultureID], [Name], [ModifiedDate] FROM [Production].[Culture]">
16                </asp:SqlDataSource>
17            </div>
18        </form>
19    </body>
20</html>

Itt egy kicsit elemzzük az OutputCache részt; hozzáadtunk egy SqlDependency tulajdonságot, majd annak értékét CommandNotification-ra állitottuk. Gyakorlatilag ezzel elértük, hogy az ehhez az oldalhoz a Query Notification működjön. A Duration tulajdonságot szándékosan állitottam nagyra, ugyanis nem akarom igazán, hogy a Cache "lejárjon", hanem akkor frissitse, amikor változik az adat mögötte.

Magában ez sajnos még kevés. A Global.asax file-hoz adjuk hozzá a következő kódrészletet:

1void Application_Start(object sender, EventArgs e)
2    {
3        // Code that runs on application startup
4        System.Data.SqlClient.SqlDependency.Start(ConfigurationManager.ConnectionStrings["AdventureWorksConnectionString"].ConnectionString);
5    }

Ha most ezt az oldalt elinditom, akkor 8 rekordot kell látnom a GridView-ban - feltéve, hogy nem változtatattam meg az eredeti tartalmát a Production.Culture táblának. Profiler-rel lekövetve az első oldal betöltését, azt vesszük észre, hogy lefuttatja a lekérdezésünket, de az oldal frissitése esetén már nem. Na akkor most adjunk hozzá egy új rekordot a következő kóddal:

Most töltsük be az oldalt és közben ellenőrizzük a Profiler-t.

1INSERT INTO Production.Culture VALUES ('hu', 'Hungarian', default)

Itt ismét meghivja a lekérdezésünket és láthatjuk, hogy egy exec sp_executesql N'BEGIN CONVERSATION TIMER...... SQL batch is fut folyamatosan. Ez utóbbi a Service Broker Service, ami a Query Notification lelke.