Cache dla danych z bazy

W każdej aplikacji, wykorzystującej bazę danych do przechowywania informacji, są elementy/tabele/struktury, których zawartość zmienia się niezmiernie rzadko. W związku z tym, zasadne wydaje się zaimplementowanie mechanizmu przechowywania tychże informacji w “bardziej stałym” obiekcie. Ograniczyłoby to komunikację pomiędzy bazą danych i aplikacją, a tym samym zwiększyło wydajność aplikacji. Mechanizm taki można zaimplementować na wiele sposobów. Jednym z nich może być klasa typu Manager do przechowywania i zarządzania informacjami. Ja natomiast pokusiłem się o implementację typu cache, którą prezentuję poniżej.

Rozpoczynamy dodając nową klasę do logiki biznesowej (zakładam, że tam jest najwłaściwsze miejsce), której nadajemy modyfikatory internal (aby klasa była dostępna tylko z tego samego assembly) oraz static (by w aplikacji istniała tylko jedna instancja tejże klasy). Następnie dodajemy kluczowe pola odpowiedzialne za działanie klasy typu cache: interwał odświeżania danych, datę ostatniego odświeżenia, znacznik czy dane należy odświeżyć oraz property zwracające obiekt z naszego cacheu. Dodatkowo dodałem zmienną typu object w celu poprawnej synchronizacji wątku za pomocą słowa kluczowego lock. Impelmentacja tych elementów wygląda następująco:

internal static class SomeDataCache
{
	private const int REFRESH_INTERVAL_MIN = 30;

	private static DataSet _Data;
	private static bool _NeedRefresh;
	private static DateTime? _LastRefreshTime;
	private static object _SyncRoot = new object();

	public static DataSet Model
	{
		get
		{
			lock (_SyncRoot)
			{
				if (_Data == null || _NeedRefresh)
				{
					_Data = ReadDataFromDatabase();
					_LastRefreshTime = DateTime.Now;
				}
				return _Data.Copy();
			}
		}
	}

	public static void SetDirty()
	{
		_NeedRefresh = true;
	}

	private static DataSet ReadDataFromDatabase()
	{
		//return some data
	}
}

Brakuje jeszcze kodu odpowiedzialnego za sprawdzanie czy nasz obiekt nie uległ przedawnieniu. Implementacja nie powinna sprawić trudności. Moja przedstawia się jak poniżej:

private static bool IsOutOfDate()
{
	return _LastRefreshTime.HasValue && _LastRefreshTime.Value.AddMinutes(REFRESH_INTERVAL_MIN) < DateTime.Now;
}

Oczywiście trzeba dodać jej wywołanie w property zwracającym obiekt.

Załóżmy sytuację, że mamy znacznik na bazie, informujący o tym, iż dane zostały zmienione. W tym przypadku należy napisać kolejny kod, odpowiedzialny za sprawdzanie tej flagi. Ja dodałem kolejny interwał oraz datę ostatniego sprawdzania znacznika. I na koniec implementacja metody do sprawdzania pola.

private const int CHECK_INTERVAL_SEC = 60;

private static DateTime? _LastCheckTime;

private static bool DataHaveChanged()
{
   if (_LastCheckTime.HasValue && _LastCheckTime.Value.AddSeconds(CHECK_INTERVAL_SEC) >= DateTime.Now)
   {
       return false;
   }

   //check flag and return bool
}

Tak jak w przypadku metody IsOutOfDate() powyższą należy również wywołać w property.

Promuj

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *