Ho due tabelle di database nella relazione genitore / figlio come una tantum.
Ho tre classi che rappresentano i dati in queste due tabelle:
Parent Class
{
Public int ID {get; set;}
.. other properties
}
Child Class
{
Public int ID {get;set;}
Public int ParentID {get; set;}
.. other properties
}
TogetherClass
{
Public Parent Parent;
Public List<Child> ChildList;
}
Infine ho un'applicazione client e server - ho il controllo di entrambe le estremità, quindi posso apportare modifiche a entrambi i programmi come è necessario.
Il cliente effettua una richiesta per ParentID e riceve una classe Together per il genitore corrispondente e tutti i record figli.
L'app client può apportare modifiche ai bambini - aggiungere nuovi bambini, rimuovere o modificare quelli esistenti. L'app client invia quindi la classe Together all'app server.
L'app del server deve aggiornare i record padre e figlio nel database.
Inoltre vorrei poter registrare le modifiche - lo sto facendo avendo due tabelle separate una per Parent, una per bambino; ciascuna contenente le stesse colonne dell'originale data di modifica aggiunta, da chi e un elenco delle modifiche.
Non sono sicuro dell'approccio migliore per rilevare le modifiche nei record: nuovi record, record da eliminare, record senza campi modificati, record con alcuni campi modificati.
Penso di aver bisogno di leggere il genitore & i bambini registrano e li confrontano con quelli della classe insieme.
Strategia A:
Se il record figlio della classe Together ha un ID di dire 0, questo indica un nuovo record; inserire. Tutti i record figli eliminati non sono più nella Classe Insieme; verificare se nessuno dei record figlio di confronto non è stato trovato nella classe Together e delete if not found (Compare using ID).
Controlla ogni record figlio per le modifiche e se ha cambiato registro.
Strategia B: Crea una nuova TogetherClass aggiornata
UpdatedClass
{
Public Parent Parent {get; set}
Public List<Child> ListNewChild {get;set;}
Public List<Child> DeletedChild {get;set;}
Public List<Child> ExistingChild {get;set;} // used for no changes and modified rows
}
E poi elaborare secondo l'elenco.
Il motivo per cui sto chiedendo idee è che entrambe queste soluzioni non mi sembrano ottimali e sospetto che questo problema sia già stato risolto - una sorta di modello di progettazione?
Sono consapevole di un potenziale problema in questo approccio generale - quello in cui l'App Client A richiede un record; L'app B richiede lo stesso record; A salva quindi i cambiamenti; B salva quindi le modifiche che potrebbero sovrascrivere le modifiche A apportate. Questo è un problema di blocco separato che solleverò una domanda a parte se ho problemi nell'implementazione.
L'implementazione effettiva è c #, SQL Server e WCF tra client e server - condivisione di una libreria contenente le implementazioni di classe.
Scusa se questo è un post duplicato - ho provato a cercare vari termini senza trovare una corrispondenza però.
Aggiornamento basato sui commenti di svick e TimG:
Per tenere traccia delle modifiche, la classe base dovrebbe essere qualcosa come:
public class ChangedRowBase
{
public enum StatusState
{
New, Unchanged, Updated, Deleted
};
protected StatusState _Status;
public StatusState Status
{
get
{
return _Status;
}
}
public void SetUnchanged()
{
_Status = StatusState.Unchanged;
}
public void SetDeleted()
{
_Status = StatusState.Deleted;
}
}
Quindi la classe di mio figlio avrebbe qualcosa del tipo:
public int SomeDumbProperty
{
get;
set
{
base.Status = StatusState.Updated;
// Missing line here to set the property itself
}
}
private int _SomeIntelligentProperty;
public int SomeIntelligentProperty
{
get { return _SomeIntelligentProperty; }
set
{
if (value != _SomeIntelligentProperty)
{
_SomeIntelligentProperty = value;
base.Status = StatusState.Updated;
}
}
}
L'idea è che l'intelligente rilevi se c'è stato davvero un cambiamento; in caso contrario, con l'uso di quello stupido l'app client dovrà rilevare la modifica e aggiornarla solo se è stata apportata una modifica oppure utilizzare comunque il setter che segnala una modifica che in realtà non si verificava.
So anche che la mia proprietà non funziona (o non compila) in questo momento. Se voglio il codice nel getter o setter, significa che devo definire una variabile privata separata io stesso? Conosco la mano corta {get; set;} fa questo dietro le quinte.