2013-05-05 12 views
13

Ich muss SqlCacheDependency für eine Tabelle implementieren, die von dieser Abfrage abhängig ist: SELECT Nickname FROM dbo.[User].Wie verwende ich SqlCacheDependency?

Ich habe eine Methode für diesen Zweck erstellt:

private IEnumerable<string> GetNicknamesFromCache() 
    { 
     const String cacheValueName = "Nicknames"; 

     var result = HttpRuntime.Cache.Get(cacheValueName) as List<String>; 
     if (result == null) 
     { 
      result = _repository.GetAllNicknames(); 

      var connectionString = ConfigurationManager.ConnectionStrings["RepositoryContext"].ConnectionString; 
      var sqlConnection = new SqlConnection(connectionString); 
      var sqlCommand = new SqlCommand("SELECT Nickname FROM dbo.[User]", sqlConnection); 
      var sqlDependency = new SqlCacheDependency(sqlCommand); 

      HttpRuntime.Cache.Insert(cacheValueName, result, sqlDependency); 
     } 

     return result; 
    } 

Aber wenn ich meine Anwendung ausführen funktioniert es nicht. Ich überprüfte die Liste der Abonnenten (sys.dm_qn_subscriptions Tabelle) und es gab keine Aufzeichnungen.

suchte ich viel Zeit und haben bereits versucht, verschiedene Lösungen, aber sie funktioniert nicht für mich:

  • Verwendung vertrauenswürdige Verbindung und einige Berechtigungen für öffentliche Rolle festgelegt:

    GRANT CREATE PROCEDURE TO public
    GRANT CREATE QUEUE TO public
    GRANT CREATE SERVICE TO public
    GRANT SUBSCRIBE QUERY NOTIFICATIONS TO public
    GRANT RECEIVE ON QueryNotificationErrorsQueue TO public

  • Gebrauch 'sa' Login für die Verbindung

  • Verwendung aspnet_regsql.exe (aspnet_regsql.exe -S localhost -E -ed -d TestTable -et -t User)
  • hinzufügen Konfiguration system.webServer in web.config:

    <caching>
    <sqlCacheDependency enabled="true">
    <databases>
    <add name="Tmpl" pollTime="5000" connectionStringName="RepositoryContext"/>
    </databases>
    </sqlCacheDependency>
    </caching>

  • legte die SqlDependency.Start() in die Global.asax Application_Start Ereignis

  • laufen auf verschiedenen Instanzen von SQL Server (SQL Server 2008 Express, SQL Server 2008)

Aber es hat nicht geholfen. Es funktioniert immer noch nicht.

Wie kann ich es funktionieren lassen?

Antwort

18

Ich habe bereits eine Lösung gefunden.

Zuerst prüfen, ob Service Broker für die Tabelle aktiviert ist und es ihr ermöglichen, bei Bedarf:

SELECT name, is_broker_enabled FROM sys.databases WHERE name = '<databaseName>' 

ALTER DATABASE <databaseName> SET enable_broker WITH ROLLBACK IMMEDIATE 

Next in SQL Server neue Rolle sql_dependency_role, erteilen Sie es schaffen und gewähren Rolle an Benutzer:

EXEC sp_addrole 'sql_dependency_role' 

GRANT CREATE PROCEDURE to sql_dependency_role 
GRANT CREATE QUEUE to sql_dependency_role 
GRANT CREATE SERVICE to sql_dependency_role 
GRANT REFERENCES on CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification] to sql_dependency_role 
GRANT VIEW DEFINITION TO sql_dependency_role 
GRANT SELECT to sql_dependency_role 
GRANT SUBSCRIBE QUERY NOTIFICATIONS TO sql_dependency_role 
GRANT RECEIVE ON QueryNotificationErrorsQueue TO sql_dependency_role 

EXEC sp_addrolemember 'sql_dependency_role', '<userName>' 

Danach fügen Sie C# -Code für die Arbeit mit SqlCacheDependency oder SqlDependency (meist auf die gleiche Weise).

Ich habe meine Methode geändert und jetzt sieht es wie folgt aus:

private IEnumerable<string> GetNicknamesFromCache() 
    { 
     const String cacheValueName = "Nicknames"; 

     var result = HttpRuntime.Cache.Get(cacheValueName) as List<String>; 
     if (result == null) 
     { 
      result = _repository.GetAllNicknames(); 

      using (var connection = new SqlConnection(_config.ConnectionString)) 
      { 
       connection.Open(); 

       SqlDependency.Start(_config.ConnectionString); 
       var command = new SqlCommand("SELECT Nickname FROM dbo.[User]", connection); 
       var dependency = new SqlCacheDependency(command); 
       HttpRuntime.Cache.Insert(cacheValueName, result, dependency); 

       command.ExecuteNonQuery(); 
      } 
     } 

     return result; 
    } 

Jetzt funktioniert es gut.

Vergessen Sie nicht, rufen Sie SqlDependency.Start Methode vor dem Erstellen SqlCacheDependency oder SqlDependency und führen Sie Ihren Befehl am Ende.

+0

Ist es notwendig, die Verbindung wie hier offen zu halten oder können Sie sie schließen/entsorgen? –

+0

Beantworten Sie meine eigene Frage oben - es ist notwendig, diese Verbindung offen zu halten, damit der Service Broker diese Benachrichtigungen senden kann. Das macht es etwas schwieriger zu entwerfen, wenn Sie viele Cache-Einträge haben, die aktualisiert werden müssen. –