EF - nadanie ParentId takiej samej wartości jak Id

0

Cześć,
chcę, aby żadne dane nie były kasowane z bazy danych a dodatkowo, aby każda zmiana była zapisywana (chcę mieć historię wszystkich zmian w bazie).
Przykładowo: jeśli użytkownik zmodyfikuje jakiś wiersz to poprzedni wiersz otrzyma status Active = false; i zostanie utworzony nowy obiekt, który będzie miał ustawiony parametr Active na true;
Każda klasa ma swój unikalny identyfikator (Id) oraz dodatkowy identyfikator ParentId, który odnosi się do danego rekordu z przed zmiany.
Przykładowo mam klasę:

public class Task
{
public int Id {get; set;}
public int ParentId {get; set;}
public string Description {get;set;}
public DateTime CreatedAt {get; set;}
public bool Acrive {get; set;}
}

Chcę, aby ParentId przy utworzeniu pierwszego nowego rekordu (Task) miał wartość równą Id, ale jednocześnie, gdy będziemy modyfikować dany rekord to aby przyjmował poprzednią wartość.
Przykładowo:
Tworzę pierwszy Task, który otrzymuje Id = 1 i ParentId = 1 oraz Active = true;
Tworzę drugi Task, który otrzymuje Id = 2 i ParentId = 2 oraz Acrive = true;
Modyfikuję pierwszy Task, dlatego Task o Id = 1 zmienia Active na false; oraz tworzony jest nowy obiekt o Id = 3 oraz ParentId = 1 oraz Acrive = true;
Tworzę kolejny obiekt Task, który otrzymuje Id = 4 oraz ParentId = 4 i Active = true;

Pytanie:
w jaki sposób zrobić, aby zmienna ParentId przy tworzeniu nowego Task-a otrzymywała wartość równą Id (które jest generowane automatycznie po stronie bazy) a przy zmianie Task-a otrzymywała poprzednią wartość?
Albo inaczej: jak zrobić, aby ParentId był równy Id, gdy nie będzie ustawiony w momencie tworzenia obiektu przez EF a w innym wypadku (gdy jest ustawiony) aby otrzymywał wartość, która jest ustawiona przy tworzeniu obiektu przez EF?

P.S. Nie chcę korzystać z Guid.

2

Chcę, aby ParentId przy utworzeniu pierwszego nowego rekordu (Task) miał wartość równą Id, ale jednocześnie, gdy będziemy modyfikować dany rekord to aby przyjmował poprzednią wartość.

a nie lepiej użyć nullable zamiast robić ludziom WTFy? :P

w jaki sposób zrobić, aby zmienna ParentId przy tworzeniu nowego Task-a otrzymywała wartość równą Id (które jest generowane automatycznie po stronie bazy) a przy zmianie Task-a otrzymywała poprzednią wartość?

1:
a gdyby publiczne property działało na zasadzie

return ParentId == null ? Id : ParentId.Value;

i odbywało się to w kodzie?

W bazie to może jakoś za pomocą computed columns? idk

2: a może trigger ON INSERT? a w kodzie już sobie obsłużysz

0
1a2b3c4d5e napisał(a):

a nie lepiej użyć nullable zamiast robić ludziom WTFy? :P

Dzięki za pomysł. Jest to jakieś rozwiązanie, ale średnio mi się podoba. Jeżeli nie będzie to możliwe to już chyba bardziej wolę zrobić ParentId jako Guid i dla modyfikowanych rekordów przepisać Guid-a. Zależy mi na tym, aby Parent i wszystkie kolejne modyfikacje miały ten sam numer ParentId - w mojej ocenie jest to troszkę bardziej czytelne z poziomu bazy danych.

1

Coś tu chyba stoi na głowie. Chcesz trzymać historię, a jednocześnie w momencie zmiany chcesz modyfikować historyczne rekordy? Może po prostu trzymaj Task i TaskVersion, i przy modyfikacjach dodawaj kolejne wersje? Nie wspominam o wersjonowaniu tabel czy event sourcingu, nie znam konkretnych wymagań.

0
Hrypa napisał(a):

Coś tu chyba stoi na głowie. Chcesz trzymać historię, a jednocześnie w momencie zmiany chcesz modyfikować historyczne rekordy? Może po prostu trzymaj Task i TaskVersion, i przy modyfikacjach dodawaj kolejne wersje? Nie wspominam o wersjonowaniu tabel czy event sourcingu, nie znam konkretnych wymagań.

Jedyne co modyfikuje w zmienianym rekordzie to parametr Active na false - aby wiedzieć, że ten rekord jest archiwalny (w sumie to parametr Active chyba powinien się nazywać Archival). Następnie dodaję nowy rekord - zmienioną kopię poprzedniego rekordu (z parametrem Active ustawionym na true).

2

Ok, ale po co? Jeśli wersjonowanie tabeli (z pudełka w MSSQL) nie załatwia sprawy, to może coś jest nie tak z implementacją? Modyfikowanie wcześniejszych rekordów tylko dla utrzymywania historii brzmi bardzo podejrzanie. Jeżeli nie masz innej opcji, trzymaj aktualną wersję w tabeli Task i rób na niej updaty, a poprzednie wartości odkładaj w TaskHistory.

1

Z opisu rozumiem tyle, że cały problem jest powodowany przez generowanie Id po stronie bazy danych. A więc moje rozwiązanie, to nie robić tego.

Alternatywnie triggery w bazie danych.

No i na 90% wydajniej mieć oddzielną tabelę na historię zmian.

0

Ok, w sumie to macie rację, że oddzielna tabela dla historii będzie lepszym rozwiązaniem.

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