Vad finns det för olika sätt att ha koll på vilka properties som ändrats på en domänentitet? Det här tycker jag är en intressant fråga, där möjligheterna ofta förbises. Det är intressant det med att spara undan orginal-entiteten innan man gör ändringarna. Om man tex har en entityBase som alla domänentiteter ärver ifrån så skulle man kunna ha orginal-entiteten i basklassen. Sedan gör man en metod som via reflection identifierar ändringar som gjorts på entiteten. Det skulle kunna fungera rätt bra. <b>>Jo, en sak funderade jag på. När du säger att ett användningsområden är att undvika onödig kommunikation. Jag tror jag förstår vad du menar men jag var bara tvungen att checka vad du menar </b> Utan att ha detaljstuderat någonting; postsharp? Man borde kunna få till någonting som exekverar snabbare än med reflection med det? -> Oskar <b>09:47:57 - Niklas Jansson Har precis implementerat tracing/loggning med postsharp och log4net. Man får ut väldigt mycket funktionalitet med få rader kod... Skulle nog inte vara några problem att bygga en bra INotifyChanged-implementation heller. Niklas, ett av få ord jag snappade upp när jag skumläste var nämligen just AOP.. ;) Postsharp råkar bara vara ett intressant jag stött på :) I NPersist så använde vi AOP för just det här. Gamlat exempel för att hantera detta via NAspect: Man ska ju definitivt skilja på applikationslogik och ramverk när det kommer till AOP a la Postsharp.Koll på vilka domänentitets-properties som blivit ändrade?
Hittills har jag enbart sett nedanstående exempel. Finns det bättre och enklare sätt?
public string FirstName
{
get { return _firstName; }
set
{
if (value == _firstName)
return;
_firstName = value;
base.OnPropertyChanged(nameOf<Customer>.Property(p => p.FirstName));
}
}
Sedan undrar jag en annan sak. I vilka användningsområden brukar man vilja ha koll på om properties blivit ändrade eller inte?Sv: Koll på vilka domänentitets-properties som blivit ändrade?
Frågorna:
Vad har "ändrats"?
och
När spelar det roll ifall något har ändrats?
Bygger egentligen på frågan:
Vad betyder "har ändrats"?
För om det stod "A", någon skriver i ett "B" och inget annat har hänt - då är det rimligtvis ändrat.
Men sen kommer det grejer.
- Vad händer om man trycker "ångra"?
- Vad händer om man ändrar tillbaks till "A"?
- Vad händer om underliggande data är ändrad av en annan användare också?
- Vad händer om en annan användare har hämtat samma data och har ändrat den, men inte sparat?
En enkel variant är att göra "Customer" till en "värdetyp", och sen ha något i stil med:
class CustomerEntity{
CustomerValue Original;
CustomerValue Current;
}
Och sen alltid jämföra original med current för att konstatera vad som är ändrat. Det gör att man helt kan slippa onödiga sparanden. Sen finns ju förstås möjligheten att ha dirty-bits - antingen per egenskap eller per entitet. Även kombination går ju (för att fånga "den här är ändrad, men har ändrats tillbaka", och hantera det).
Sen kommer nästa steg och det är concurrency - vad ska hända om någon annan har ändrat värdet före jag blev klar för att spara?
Och där är det ju enklast att kolla på revisionskontrollssytem för tips. Antingen skita i vilket och skriva över (a'la filsystem), eller med låsningar så att problemet inte uppstår (CVS, source safe, osv.), eller SVN-varianten, vilket jag föredrar - det är en jävligt cool lösning (om tillåtet uttrycks om något så nördigt). Där kan man ju också slänga på en hel hinting-mekanism också.
Men detta borde väl vara inbyggt i de flesta ORM osv? Jag är för dåligt insatt i dem, tyvärr.
Annars kan nog en aop-lösning bli rätt snygg för att hantera det.
Användningsområdena är väl framför allt för användargränssnitt, för att undvika onödig kommunikation, och för cuncurrency.Sv:Koll på vilka domänentitets-properties som blivit ändrade?
En sak som man bör tänka på är att det måste vara olika instanser i orginal- och current-entiteten samt underliggande instanser så att inte en ändring i tex current-entiteten slår på orginal-entiteten. Men det borde man märka ganska snabbt...
Om du kör utan ORM så borde concurrency-delen lösa sig ganska enkelt om du i entiteten tex rowversion.
Jo, en sak funderade jag på. När du säger att ett användningsområden är att undvika onödig kommunikation. Jag tror jag förstår vad du menar men jag var bara tvungen att checka vad du menar :)
Du nämnde också något om AOP. Har du sett någon sådan lösning där detta tillämpas? Skulle vara intressant att se hur de löst det...Sv: Koll på vilka domänentitets-properties som blivit ändrade?
Ja, helt enkelt att icke ändrade delar behöver man inte uppdatera. I Customer med "Name" och "InvoiceAdress" är det förstås meningslöst, men i större entiteter kan det vara relevant.
<b>>Du nämnde också något om AOP. Har du sett någon sådan lösning där detta tillämpas? Skulle vara intressant att se hur de löst det...</b>
Nä, inte sett. Spontant infall bara, det känns som att det är en cross-cutting concern som är nästan helt oberoende av vad som lagras.Sv: Koll på vilka domänentitets-properties som blivit ändrade?
Sv:Koll på vilka domänentitets-properties som blivit ändrade?
Har du testat Postsharp i något avseende? Erfarenheter? Jag hittade denna sida om Postsharp: http://www.postsharp.org
Ska kolla på videon senare ikväll...Sv:Koll på vilka domänentitets-properties som blivit ändrade?
>Annars kan nog en aop-lösning bli rätt snygg för att hantera det.</b>
<b>12:44:27 - Oskar Johansson
>Utan att ha detaljstuderat någonting; postsharp?</b>
=DSv: Koll på vilka domänentitets-properties som blivit ändrade?
Sv: Koll på vilka domänentitets-properties som blivit ändrade?
Sv: Koll på vilka domänentitets-properties som blivit ändrade?
(Via NAspect)
Vi mixade in en OriginalState mixin per entitet, den håller reda på alla properties orginalvärden.
I sin naivaste form så kan man tänka sig den som en hashtabell med propertynamn som key och propertyvärde som value.
På så sätt kan man jämföra alla properties current state med dess original state.
och då se om något förändrats.
Man behöver därför ingen "interception" hantering för att hantera dirty tracking.
Dock hade vi även interception för att se _när_ något ändrades, för att på så sätt även kunna AOP'a på databinding stöd etc.Sv:Koll på vilka domänentitets-properties som blivit ändrade?
http://www.puzzleframework.com/wikiengine/WikiPageViewer.aspx?id=102
Det finns två stora skillnader på vad NAspect och Post# gör.
Post# är en post compiler som kan lägga aspects på i princip allt genom att misshandla IL koden i ett eget kompileringssteg.
NAspect är baserat på dynamic proxies, dvs den genererar subclasser av det du vill lägga aspekter på.
Och kräver då att klassen inte är "sealed" och att de metoder du vill förändra är "virtual".
Alla instancer måste även skapas via ett factory.
MS Entity Framework 4 som kommer nu med .NET 4 bygger på samma teknik som NAspect.
Post# är extremt kraftfullt, så pass att jag anser att den tillåter att du bryter eller helt ignorerar vedertagna regler i OOP.
http://rogeralsing.com/2008/01/08/code-mangling-aop-vs-runtime-proxy-aop/Sv: Koll på vilka domänentitets-properties som blivit ändrade?
Att sas utöka ramverkat med trace & logg ser jag ingen problem med, det har ju väldigt lite med applikationen i sej att göra.
Att hålla ordning på properties är väl något av ett gränsfall kan jag tycka, men håller man det helt rent från affärslogik så varför inte?
Proxies är ju en jättebra lösning, om man har möjlighet att börja från scratch med IoC-containers osv. Men i befintliga applikationer kan det vara svårare.