Eu tenho duas tabelas de banco de dados no relacionamento pai / filho como um-muitos.
Eu tenho três turmas representando os dados nessas duas tabelas:
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;
}
Por fim, tenho um aplicativo de cliente e servidor - estou no controle de ambas as extremidades para poder fazer alterações em ambos os programas, conforme necessário.
O cliente faz uma solicitação de ParentID e recebe uma Together Class para o pai correspondente e todos os registros filhos.
O aplicativo cliente pode fazer alterações nos filhos - adicione novos filhos, remova ou modifique os existentes. O aplicativo cliente envia a Together Class de volta ao aplicativo do servidor.
O aplicativo do servidor precisa atualizar os registros pai e filho no banco de dados.
Além disso, gostaria de poder registrar as alterações. Estou fazendo isso com duas tabelas separadas, uma para pai e outra para filho; cada um contendo as mesmas colunas que o original, mais a data e hora modificadas, por quem e uma lista das alterações.
Não tenho certeza sobre a melhor abordagem para detectar as alterações nos registros - novos registros, registros a serem excluídos, registros sem campos alterados, registros com alguns campos alterados.
Eu acho que preciso ler o pai & registros de crianças e compare-os com os da Classe Juntos.
Estratégia A:
Se o registro filho da turma Juntos tiver uma ID de 0, isso indica um novo registro; inserir.
Todos os registros filhos excluídos não estão mais na classe Juntos; veja se algum dos registros filho de comparação não foi encontrado na classe Together e exclua se não encontrado (Compare usando ID).
Verifique se há alterações no registro de cada filho e se o log foi alterado.
Estratégia B:
Faça um novo TogetherClass Atualizado
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, em seguida, processe conforme a lista.
A razão pela qual estou pedindo ideias é que ambas as soluções não parecem ideais para mim e suspeito que esse problema já tenha sido resolvido - algum tipo de padrão de design?
Estou ciente de um problema em potencial nessa abordagem geral - onde o Aplicativo do Cliente A solicita um registro; App B solicita o mesmo registro; A então salva as alterações; B salva as alterações que podem sobrescrever as alterações feitas. Este é um problema de bloqueio separado, que levantarei uma questão diferente se eu tiver problemas para implementar.
A implementação real é c #, SQL Server e WCF entre cliente e servidor - compartilhando uma biblioteca contendo as implementações de classe.
Desculpas se este for um post duplicado - tentei pesquisar vários termos sem encontrar uma correspondência.
Atualize com base nos comentários do svick e do TimG:
Para acompanhar a mudança, a classe base seria algo como:
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;
}
}
Então minha turma infantil teria algo como:
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;
}
}
}
A idéia é que o inteligente detecta se realmente houve uma mudança; caso contrário, usar o mudo que o aplicativo cliente precisaria para detectar a alteração e atualizar somente se houve uma alteração, ou usar o setter de qualquer maneira sinalizando uma alteração que realmente não ocorreu.
Eu também sei que a minha burrice não funciona (ou compila) agora. Se eu quiser código no getter ou setter, isso significa que eu preciso definir uma variável privada separada eu mesmo? Eu conheço o ponteiro curto {get; set;} faz isso nos bastidores.