Qual é a maneira correta de lidar com entidades de auto-rastreamento que não rastreiam?
-
21-09-2019 - |
Pergunta
Entidades de auto -rastreamento. Incrível.
Exceto quando você faz algo como
return Db.Users;
Nenhuma das entidades de auto-rastreamento está rastreando (até que, possivelmente, elas sejam desserializadas).
Multar. Portanto, temos que reconhecer que existe a possibilidade de que uma entidade retorne a nós não tenha rastreamento ativado.
O que agora???
Coisas que eu tentei
Para o corpo do método especificado:
using (var db = new Database())
{
if (update.ChangeTracker.ChangeTrackingEnabled)
db.Configurations.ApplyChanges(update);
else
FigureItOut(update, db);
db.SaveChanges();
update.AcceptChanges();
}
As seguintes implementações de FigureItOut
Tudo falha:
db.Configurations.Attach(update);
db.DetectChanges();
Nem
db.Configurations.Attach(update);
db.Configurations.ApplyCurrentValues(update);
Nem
db.Configurations.Attach(update);
db.Configurations.ApplyOriginalValues(update);
Nem
db.Configurations.Attach(update);
db.Configurations.ApplyChanges(update
Nem sobre mais nada que eu possa imaginar para jogar, exceto
- Obtendo a entidade original do banco de dados
- Comparando cada propriedade manualmente
- Atualizando propriedades conforme necessário
O que, exatamente, devo fazer com entidades auto-rastreadas que não estão se rastreando?
Pequena atualização:
Marcar cegamente a entidade como obras modificadas, no entanto, isso parece um pouco fedorento. É o melhor que podemos fazer neste caso?
Solução
Cenário 1
Aqui estão algumas práticas recomendadas a seguir. Quando você está usando o STE no cenário WCF, você deve confiar no rastreador de mudança que o STE implementa para que, no lado do servidor, você faça o seguinte.
db.Users.ApplyChanges(user);
db.SaveChanges();
Cenário 2 No entanto, se você estiver no servidor, a prática recomendada é criar um método na classe parcial para o ObjectContext chamado EnableChangeTracking. O método consultaria as entidades que estão em indicação inalterada que implementa o IObjectwithChangeTracker e liga o rastreamento de alterações, então algo assim
user = db.users.first(u => u.userid == 1);
db.EnableChangeTracking();
Agora tente salvar a entidade do usuário de um contexto diferente do qual foi originalmente recuperado
db2.users.ApplyChanges(user);
db2.SaveChanges();
Cenário 3 Se no lado do servidor você estiver conectado ao mesmo contexto de objeto a partir do qual você recuperou a entidade do usuário, então você usa o sTE como objeto poco simples como abaixo
user = db.users.first(u => u.userid == 1);
user.LastName = "XYZ";
db.DetectChanges(); //no need for it cuz Savechanges implicitly calls this.
db.SaveChanges();
Cenário 4 Se a entidade do usuário for recuperada de um contexto diferente, o contexto que você usará para salvar, aqui está outra opção em que você marcará a entidade como modificada e não se importará com o que foi modificado.
user = db.users.first(u => u.userid == 1);
var db2 = new ObjectContext();
user.LastName = "XYZ";
db2.Users.Attach(user);
// i prefer this option..
db2.ObjectStateManager.ChangeObjectState(user,EntityState.Modified);
db2.SaveChanges(); // updates all columns
Cenário 5 Se a entidade do usuário for recuperada de um contexto diferente, o contexto que você usará para salvar, aqui está outra opção em que você recupera a entidade original.
user = db.users.first(u => u.userid == 1);
user.lastName ="XYZ";
var db2 = new ObjectContext();
db2.Users.First(u => u.userid == user.userid);
db2.users.ApplyCurrentValues(user);
db2.SaveChanges();
Aqui está um post de blog que descreve poucos cenários.http://weblogs.asp.net/zeeshanhirani/archive/2010/03/30/modifying-self-tracking-entity-on-the-sherver.aspx
Eu cobro extensivamente esses conceitos em minha estrutura de entidade 4.0 Receitas, com muitos cenários.