Sincronize o Cache de Objeto Distribuído com o SQL Server 2008/2012

Autor: Iqbal Khan

NCache permite armazenar dados em cache mais próximos de seu aplicativo na camada intermediária para que você possa reduzir viagens caras ao banco de dados. Isso, por sua vez, acelera significativamente sua aplicação. Também o torna mais escalável porque a carga em seu banco de dados é reduzida, permitindo que ele lide com um número maior de clientes sem atualizações de hardware.

No entanto, quando você armazena dados em cache, na verdade está criando uma cópia deles fora do banco de dados. Isso apresenta o risco de que os dados em seu banco de dados sejam modificados, mas sua cópia em cache permaneça inalterada e se torne obsoleta. A boa notícia é que essa situação ocorre apenas quando você tem vários aplicativos modificando os mesmos dados no banco de dados e quando nem todos estão atualizando o cache.

Quando você tem a situação em que outros aplicativos estão modificando dados no banco de dados e não atualizando o cache, você precisa de um mecanismo para que o cache possa se sincronizar diretamente com o banco de dados. Isso é possível de várias maneiras diferentes. Se seu banco de dados for SQL Server 2008/2012, o cache poderá usar notificações de eventos .NET para sincronização, o que é bastante eficiente. Mas, se seu banco de dados for SQL Server 2000, Oracle ou qualquer outro banco de dados compatível com OLEDB, a única maneira de sincronizar é pesquisando o banco de dados em busca de atualizações. Esse método obviamente não é tão eficiente porque o cache acaba fazendo muitas viagens desnecessárias ao banco de dados.

Neste artigo, vou discutir como NCache sincroniza o cache com o banco de dados SQL Server 2008/2012 usando notificações de eventos .NET.

Especificando SqlCacheDependency em código

Aqui está o que você precisa especificar no código do seu aplicativo .NET para usar esse recurso. NCache fornece uma interface muito semelhante ao da Microsoft SqlCacheDependency interface porque internamente NCache está usando SqlCacheDependency objeto para sincronizar com o SQL Server 2008/2012.

public class Program {

public static void Main(string[] args)
    {
        NCache.InitializeCache("myCache");
        Customer cust = new Customer();
        cust.CustomerID = "ALFKI";
        LoadCustomer(cust);

        List<Customer> custList = FindCustomers("San Francisco");

        // Do your regular work here...

        NCache.Cache.Dispose();
    }

// A standard Load method that loads a single row from database
public Customer LoadCustomer(Customer cust)
    {
        String key = "Customer:CustomerID:" + cust.CustomerID;
        Customer cust2 = (Customer)NCache.Cache.Get(key);
        if (cust2 != null)
        return cust2;

        CustomerFactory custFactory = new CustomerFactory();

        // Load a single customer from the database
        // SELECT * FROM Customers WHERE CustomerID = 'ALFKI'
        custFactory.Load(cust);

        // Create a SqlCacheDependency for this item
        CacheItem item = new CacheItem(cust);
        item.Dependency = SqlDependencyFactory.CreateSqlYukonDependency(connectionString,
        "SELECT CustomerID FROM Customers WHERE CustomerID = '" + cust.CustomerID + "'");

        // Store item in the cache along with SqlCacheDependency
        NCache.Cache.Insert(key, item);
        return cust;
    }

    // A query method
    public List<Customer> FindCustomers(String city)
        {
            String key = "List<Customer>:City:" + city;
            List<Customer> custList = (List<Customer>)NCache.Cache.Get(key);
            if (custList != null)
            return custList;

        CustomerFactory custFactory = new CustomerFactory();

        // Load a list of customers from database based on a criteria
        // SELECT * FROM Customers WHERE City = 'San Francisco'
        custList = custFactory.FindByCity(city);

        // Create a SqlCacheDependency for this list of customers
        CacheItem item = new CacheItem(custList);
        item.Dependency = SqlDependencyFactory.CreateSqlYukonDependency(connectionString,
        "SELECT CustomerID FROM Customers WHERE City = '" + city + "'");

        // Store list of customers in the cache along with SqlCacheDependency
        NCache.Cache.Insert (key, item);
        return custList;
    }
}

O código acima mostra duas situações diferentes onde você pode especificar SqlCacheDependency. A primeira é quando você carrega uma única linha do banco de dados, converte-a em um objeto e armazena-a no cache. Nesse caso, observe que você deve especificar uma instrução SQL equivalente usada em seu código para buscar esta única linha. Esta instrução SQL é então usada por SqlCacheDependency objeto para estabelecer uma conexão com o banco de dados e registrar as linhas para as quais o SQL Server 2008/2012 deve enviar notificações de eventos .NET.

A segunda situação é onde você está buscando uma coleção de linhas do banco de dados como uma coleção de objetos e, em seguida, armazenando a coleção inteira como um objeto individual no cache. Neste caso, você precisa criar um SqlCacheDependency que usa a mesma instrução SQL para buscar as mesmas linhas que você acabou de fazer no banco de dados. Deste jeito, NCache notifica o SQL Server 2008/2012 que, quando qualquer uma dessas linhas for alterada, uma notificação de evento .NET deve ser enviada para NCache.

O exemplo de código acima cobre a maioria das situações em que você precisaria especificar um SqlCacheDependency em seu código. Outra situação é quando você está tentando buscar uma coleção de objetos relacionados ao Cliente (por exemplo, relacionamento 1-n). Nessa situação, você fará exatamente o que fez para buscar uma coleção de objetos Customer. A única coisa que mudaria é a instrução SQL que está sendo usada para buscar objetos relacionados.

Observe que a instrução SQL que você fornece CreateSqlYukonDependency() método não deve usar "SELECT * ..." formato. Você deve especificar um ou mais nomes de coluna como parte do SELECT declaração. Por outro lado, SqlCacheDependency não vai funcionar.

Habilitar Service Broker no SQL Server 2008/2012

Você deve habilitar o service broker no SQL Server 2008/2012 antes NCache pode usar SqlCacheDependency. Isso permite que o SQL Server 2008/2012 envie notificações de eventos para NCache para que ele saiba que os dados foram alterados no banco de dados.

ALTER DATABASE Northwind SET ENABLE_BROKER;
GO

Por favor, note que NCache liga automaticamente SqlCacheDependency.Start() método de dentro de seu próprio código. Você nunca interage diretamente com SqlCacheDependency e, portanto, não precisa ligar "Start()" método sobre ele.

Executar aplicativo

Agora você está pronto para executar seu aplicativo que torna NCache chamadas para armazenar dados em cache. Agora, sempre que você armazenar em cache qualquer coisa em NCache, NCache notifica o SQL Server 2008/2012 sobre isso e, quando esses dados são alterados no SQL Server 2008/2012, ele envia uma notificação de evento .NET para NCache. NCache em seguida, remove esses dados do cache porque eles foram alterados no banco de dados. Dessa forma, da próxima vez que seu aplicativo precisar desses dados, ele não os encontra no cache e vai até o banco de dados para buscá-los e depois armazena no cache.

Conclusão

Como você viu, NCache torna muito simples sincronizar seu cache distribuído com seu banco de dados SQL Server 2008/2012. Agora, você pode ficar tranquilo sabendo que seu cache nunca fica fora de sincronia com seu banco de dados.


Autor: Iqbal Khan trabalha para Alachisoft , uma empresa de software líder que fornece soluções de cache distribuído .NET e Java, mapeamento O/R e otimização de armazenamento do SharePoint. Você pode alcançá-lo em iqbal@alachisoft.com.

© Copyright Alachisoft 2002 - . Todos os direitos reservados. NCache é uma marca registrada da Diyatech Corp.