2013-05-05 5 views
13

Devo implementare SqlCacheDependency per una tabella che dipenderà da questa query: SELECT Nickname FROM dbo.[User].Come utilizzare SqlCacheDependency?

ho creato un metodo per questo scopo:

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; 
    } 

Ma quando eseguo la mia applicazione che non funziona. Ho controllato l'elenco degli abbonati (tabella sys.dm_qn_subscriptions) e non ci sono stati record.

ho studiato molto tempo e hanno già provato varie soluzioni, ma non funziona per me:

  • uso connessione attendibile e impostare alcuni permessi per ruolo pubblico:

    GRANT CREATE PROCEDURE TO public
    GRANT CREATE QUEUE TO public
    GRANT CREATE SERVICE TO public
    GRANT SUBSCRIBE QUERY NOTIFICATIONS TO public
    GRANT SELECT ON OBJECT::dbo.[User] TO public
    GRANT RECEIVE ON QueryNotificationErrorsQueue TO public

  • uso di accesso 'sa' per il collegamento

  • uso aspnet_regsql.exe (aspnet_regsql.exe -S localhost -E -ed -d TestTable -et -t User)
  • aggiungere configurazione per system.webServer nel web.config:

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

  • mettere lo SqlDependency.Start() nell'evento Global.asax Application_Start

  • corsa a diverse istanze di SQL Server (SQL Server 2008 Express, SQL Server 2008)

Ma non ha aiutato. Ancora non funziona.

Come faccio a farlo funzionare?

risposta

18

Ho già trovato una soluzione.

Al primo controllo se Service Broker sia abilitato per la vostra tavola e consentire, se necessario:

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

ALTER DATABASE <databaseName> SET enable_broker WITH ROLLBACK IMMEDIATE 

Successivo creare in SQL Server nuovo ruolo sql_dependency_role, concedere autorizzazioni ad esso e concedere il ruolo di utente:

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>' 

Successivamente aggiungere codice C# per lavorare con SqlCacheDependency o SqlDependency (principalmente allo stesso modo).

ho cambiato il mio metodo e adesso sembra che questo:

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; 
    } 

Ora funziona benissimo.

Non dimenticare di invocare il metodo SqlDependency.Start prima di creare SqlCacheDependency o SqlDependency ed eseguire il comando alla fine.

+0

È necessario mantenere la connessione aperta come hai fatto qui o puoi chiuderla/smaltirla? –

+0

Risposta alla mia domanda precedente: è necessario mantenere aperta questa connessione in modo che il broker dei servizi possa inviare tali notifiche. Ciò rende un po 'più difficile da progettare in giro se si hanno molte voci della cache che devono essere aggiornate. –