O método RevertChangesSingleEntity() tem suas restrições, por exemplo não trata o caso da entity ter sido adicionada. Este cenário deve ser revertido com o detach da entity de seu context, embora a entidade continuará a existir fora dele. Importante frisar que o método ObjectContext.Detach() atua em uma única entity por vez, e desintegra o grafo que participava, pois não pode haver parte do grafo no contexto e outra parte fora. Pode pensar nisso como o gato de Schrödinger. Isto significa que o se eu tiver um Pedido e uma coleção ItemDoPedido adicionados no contexto, para reverter esta inclusão é preciso detach cada objeto individualmente. Entretanto o Pedido ficaria desconectado de seus ítens. Outra característica do detach é que a entrada (classe ObjectStateEntry) no change tracker permanece com a EntityKey e o State anterior, porém a propriedade Entity será nula pois foi desconectada.
Uma outra maneira de parar o change tracking dos objeto é executar IEntityWithChangeTracker.SetChangeTracker() passando null como o único parâmetro. Isto remove o IEntityChangeTracker que monitora e registra as alterações no objeto. A vantagem disso é que o grafo permanece intacto, e a desvantagem é que parte do grafo continua registrando as alterações e parte não mais.
Acontece que adicionar/deletar uma entidade em um relacionamento implica em manter outras entradas no ObjectStateManager referente aos relacionamentos, como podemos ver na imagem a seguir.
Segue código para tratar a reversão das associações:
public static void RevertChanges(this ObjectContext db)
{
foreach (var ose in db.ObjectStateManager.GetObjectStateEntries(EntityState.Added))
ose.Delete();
foreach (var ose in db.ObjectStateManager.GetObjectStateEntries(EntityState.Modified))
{
if (!ose.IsRelationship)
{
var org = ose.GetUpdatableOriginalValues();
var props = ose.GetModifiedProperties();
foreach (var prop in props)
{
var x = ose.Entity.GetType().GetProperty(prop);
x.SetValue(ose.Entity, org.GetValue(org.GetOrdinal(prop)), null);
}
}
}
foreach (var ose in db.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted))
if (!ose.IsRelationship)
ose.ChangeState(EntityState.Unchanged);
db.AcceptAllChanges();
}
(to be continued...)
sexta-feira, 9 de abril de 2010
Assinar:
Postar comentários (Atom)
Nenhum comentário:
Postar um comentário