Baza danych - logi

0

Witam,
Tworząc aplikację bazodanową warto wykonać logi.
Chciałem zrobić jedną uniwersalną tabelę z logami.
Wyglądałaby mniej-więcej tak:

tbLogs

  • id
  • idUztkownik // kto dokonal zmiany
  • RodzajLogu // czego log dotyczy - grupy, funkcji, usera itd.
  • Data // kiedy nastapila modyfikacja danego elementu
  • idDaneStare // dane historyczne
  • idDaneNowe // dane nowe
  • powod // Powód modyfikacji - nieobowiązkowy

Tabela taka w polach idDaneStare i IDDaneNowe przechowuje ID-ki do innych tabel (tbUser, tbFunction, tbGroup itd.).
To do czego id tego obiektu należy uwarunkowane jest w polu "RodzajLogu", gdzie symbol "U" dotyczy usera, "G" grupy itd.

Teoretycznie działałoby to na poziomie bazy dobrze. Jednak pisząc aplikację chciałbym od razu załadować cały obiekt do pamięci.
Tzn:
tbLogs.Load(id: 5);
I wszystkie pola uzupełnione - w tym także pola dotyczące danych historycznych i nowych. W aplikacji odtworzyłęm strukturę, jednak zrobiłem to w ten sposób:

public class Log : IdentifyData
    {
        private User user = new User();
        private DictionaryConcept typeLogs = new DictionaryConcept();
        private DateTime date = DateTime.Now;
        private IdentifyData oldData = new IdentifyData();
        private IdentifyData newData = new IdentifyData();
        private string reason = string.Empty;

Ładując dane:

        public IdentifyData Load(int id)
        {
            DataTable table = this.db.Select(id);

            if (table.Rows.Count > 1)
                throw new Exception("Pobrano zbyt wiele danych.");

            if (table.Rows.Count == 0)
                return null;

            return this.ConvertTo(table.Rows[0]);
        }

        protected override QuestionnaireLib.IdentifyData ConvertTo(System.Data.DataRow row)
        {
            Log con = new Log();
            con.ID = Convert.ToInt32(row["ID"]);
            con.Date = Convert.ToDateTime(row["Date"]);
            con.NewData   // Tutaj nie wiem z jakiej klasy korzystać
            con.OldData    // Tutaj nie wiem z jakiej klasy korzystać
            con.Reason = row["Reason"].ToString();
            
            DictionaryConcept dic = new DictionaryConcept();
            dic.Load(Convert.ToInt32(row["TypeLogs"]));
            con.TypeLogs = dic;

            User user = new User();
            user.Load(Convert.ToInt32(row["IDUser"]));
            con.User = user;
            return con;
        }

Nie wiem jak załadować dane nowe i historyczne. Musiałbym wykonać switcha i sprawdzać typ logu, co nie bardzo mi odpowiada ze względów estetycznych.
Jak widzicie typ logu jest także konkretnym obiektem, a nie zwykłym id, ale na poziomie logiki już wiemy jaka to klasa. Z danymi historycznymi i nowymi tak nie jest, gdyż mogą to być jakiekolwiek inne klasy.

Czy jest na to jakiś lepszy sposób?
Pozdrawiam.

0

Na razie wymyśliłem jedynie, że będę zapisywał klasę, której dany wpis dotyczy.
Czyli zamiast w typie logu wpisywać "U", wpisze nazwę klasy: "User".

Wtedy podczas mapowania obiektu wykonam taki kod:

            Type type = Type.GetType(row["TypeLog"].ToString());
            IdentifyData dataOld = (IdentifyData)Activator.CreateInstance(type);
            dataOld.Load(ID);

I jest to dobry sposób. niemniej może ktoś ma inny pomysł?

0

To nie logi tylko dane audytowe.

Inne pomysły, jeśli chodzi o przechowywanie takich danych:

  1. Jedna tabela audytowa dla jednej tabeli danych.
  2. Jedna tabela przechowująca informacje o zmienionych wartościach, a nie całych rekordach (struktura mniej więcej taka: id, tabela, idRekordu, kolumna, staraWartość, nowaWartość).
  3. Użyć mechanizmu wbudowanego w silnik bazy danych. (To zadziała jako 1, albo 2, ale wydajnie i za darmo).

Jeśli chodzi o odczyt:
4) Użyć ORM i nie tracić czasu na wynajdowanie koła na nowo.

0

Jak powiedział @somekind to dane audytowe. Jak byś jednak chciał gromadzić logi to polecam ElasticSearch + Heka.

1 użytkowników online, w tym zalogowanych: 0, gości: 1