Usuário com melhor resposta
EF com windows form

Pergunta
-
Galera,
Qual seria uma boa maneira de trabalhar com o EF usando windows forms?? eu começei um projeto deixando o context no MDI form e passo para os forms filhos esse mesmo contexto, ou seja, uso um contexto durante toda a execução do programa. Existe algum maneira melhor para fazer isso ou a microsoft orienta usar assim??
Caso eu esteja fazendo certo, como fica o seguinte cenario... imagine que ao abrir o form "ListarClientes" e clicar na linha da grid passando o objeto da linha correspondente para o form "EditarCliente"... bom, eu faço um monte de edição no objeto, ai no final eu desisto das edições e cancelo a edição.. bom, ai que esta o problema, eu ja alterei diretamente no objeto e quando eu volto a listagem o objeto ja esta alterado, como faço para resolver esse problema??
vlww
Ozzyvegeta
Respostas
-
Olha nao sei se é a melhor forma... mas eu gosto de criar um contexto estatico no Program.... ja que Windows Forms é mono-usuario mesmo...
What would Brian Boitano do ?
((2B || !2B) is Question) ?- Sugerido como Resposta AndreAlvesLimaModerator sexta-feira, 7 de maio de 2010 23:23
- Marcado como Resposta AndreAlvesLimaModerator sexta-feira, 14 de maio de 2010 15:15
-
Olha ate tem... é que eu normalmente trabalho com o EF num WebService.. entao nao tenho esse tipo de problema... mas se nao me engando se vc fizer:
context.Refresh(RefreshMode.ClientWins, entity);
fora isso, da para adaptar algo sim... tipo to sem muito tempo de testar agora... mas da uma olhada nisso aqui e ve se te ajuda:
public static void CancelCurrentChanges(this ObjectContext context, ref object entity) {
var entry = context.ObjectStateManager.GetObjectStateEntry(entity);
for (int i = 0; i < entry.OriginalValues.FieldCount; i++) {
var name = entry.OriginalValues.GetName(i);
var value = entry.OriginalValues.GetValue(i);var property = entity.GetType().GetProperty(name);
if (property == null) continue;
property.SetValue(entity, value, null);
}
}- Sugerido como Resposta AndreAlvesLimaModerator sexta-feira, 7 de maio de 2010 23:23
- Marcado como Resposta AndreAlvesLimaModerator sexta-feira, 14 de maio de 2010 15:15
-
Alias... se for no 4.0 ja tem o metodo para isso:
context.ObjectStateManager.GetObjectStateEntry(entidade).ApplyOriginalValues(entidade);
What would Brian Boitano do ?
((2B || !2B) is Question) ?- Sugerido como Resposta AndreAlvesLimaModerator sexta-feira, 7 de maio de 2010 23:23
- Marcado como Resposta AndreAlvesLimaModerator sexta-feira, 14 de maio de 2010 15:15
-
Entao... nos meus WS quando eu recebo a Entidade via paramentro no meu webmethod ela ja vem desattachada bunitinha como tem que ser e o Attach ____ numa boa... eu so do um:
if (this.EntityState == System.Data.EntityState.Detached) context.Attach(this); para caso eu teje chamando o metodo internalmente ....
mas enfim... volta a questao que ja falei noutro post aqui... EF é não ferramenta para sistema de altaperformance.... enquanto vc quiser escovar bites "nao indo desncessariamente ao banco" não é usando EF que vai fazer isso....
como eu uso webservice... meu acesso a dados fica centrado em 1 unico servidor... que aguenta muito... entao nao esquento com quantidade de acessos ao BD...
mesmo pq o Sql tem tanto poolings e caches internos... que nao perde performance em nada... mas enfim... eu gosto de ficar dando FirstOrDefault o tempo todo para verificar se o registro foi ou nao alterado por outro usuario antes de fazer qq processamento com a entidade q recebo no webmethod....
What would Brian Boitano do ?
((2B || !2B) is Question) ?- Sugerido como Resposta AndreAlvesLimaModerator sexta-feira, 7 de maio de 2010 23:23
- Marcado como Resposta AndreAlvesLimaModerator sexta-feira, 14 de maio de 2010 15:15
Todas as Respostas
-
Olha nao sei se é a melhor forma... mas eu gosto de criar um contexto estatico no Program.... ja que Windows Forms é mono-usuario mesmo...
What would Brian Boitano do ?
((2B || !2B) is Question) ?- Sugerido como Resposta AndreAlvesLimaModerator sexta-feira, 7 de maio de 2010 23:23
- Marcado como Resposta AndreAlvesLimaModerator sexta-feira, 14 de maio de 2010 15:15
-
entendo, bom, de uma forma ou de outra vc esta trabalhando da mesma forma que eu, inclusive tive a mesma conclusao por ser monousuario. Mais assim, será q isso eh a melhor maneira? e como vc trabalha quando precisa cancelar uma edição? o objeto foi alterado e eh preciso um "rollback" vamos se dizer assim para que o savechanges não o afete. ?
eu to usando o metodo Refresh com o ENUM StoregWins para esse "RollBack", mais isso tem um custo de ir na base novamente apenas pq o cara clicou em "Cancelar".
Ozzyvegeta -
Entao... eu faço Rollback a moda antiga mesmo :)
da uma olhada nisso aqui que eu faço para dar o AcceptAllChanges e dar um rollback em caso de Exception
public static void CommitAllChanges(this ObjectContext context) { context.CommitAllChanges(IsolationLevel.Unspecified); } public static void CommitAllChanges(this ObjectContext context, IsolationLevel isolationLevel) { if (context.Connection.State != ConnectionState.Open) context.Connection.Open(); var transaction = context.Connection.BeginTransaction(isolationLevel); try { context.AcceptAllChanges(); transaction.Commit(); } catch { transaction.Rollback(); throw; } }
What would Brian Boitano do ?
((2B || !2B) is Question) ? -
ha entao.. quando eu disse "RollBack" foi um modo de dizer rsrs... eu quis dizer voltar os valores iniciais da entidade antes de ser editada pelo FORM... exemplos..
Chamando o form de edição
----------------------------------
var cxt = Program.GetContext()// Metodo static criado para recuperar o context unico.
var cliente = cxt.ClienteSet.FirstOrDefault();
var frmCliente = new frmCliente();
frmCliente.ClienteEdit = cliente; // Esse propriedade seta o cliente para ser editado
frmCliente.Init(); // Esse metodo init faz o binding dos valores para os campos e o logo show
----------------------------
Metodo de Save do form de edição
-------------------------------------------
var cxt = Program.GetContext();
cxt.SaveChanges(); // Até aqui tranquilo, faz o save e ja era...
A questão é que estou trabalhando com aquela ferramenta de DataBinding do .net (esqueci de comentar isso antes), ou seja, ele afeta o objeto no momento que o cara digita (no on change de um textfield) , por exemplo. Ai quando eu faço um CANCEL o objeto ja foi afetado e nesse momento eu tenho um problema pq qualquer outro savechanges ocorrer vai fazer persistir essa alteração que foi CANCELADA. Ai pensei, sera q não existe algum meio de voltar a entidade para os valores originais? Ai eu encontrei a solução de no metodo de cancel fazer um Refresh na entidade, porem dessa forma eu perco em performance por ter que ir na base. E detalhe, por causa apenas um CANCEL! :(... por isso veio o meu desconforto em usar dessa maneira e queria saber se alguem ja teve esse tipo de problema e conseguiu uma solução mais elegante que a minha. Eu até pensei em copiar os valores para outra entidade fora do contexto e trabalhar em cima dela, porem ai sai da ideia inicial dessa arquitetura.
E a pergunta eh... sera que existe uma maneira padrão que a MS proproe quando opta por apenas um context em toda a aplicação para não persistir essas alterações que foram canceladas?
[]s
Ozzyvegeta -
Olha ate tem... é que eu normalmente trabalho com o EF num WebService.. entao nao tenho esse tipo de problema... mas se nao me engando se vc fizer:
context.Refresh(RefreshMode.ClientWins, entity);
fora isso, da para adaptar algo sim... tipo to sem muito tempo de testar agora... mas da uma olhada nisso aqui e ve se te ajuda:
public static void CancelCurrentChanges(this ObjectContext context, ref object entity) {
var entry = context.ObjectStateManager.GetObjectStateEntry(entity);
for (int i = 0; i < entry.OriginalValues.FieldCount; i++) {
var name = entry.OriginalValues.GetName(i);
var value = entry.OriginalValues.GetValue(i);var property = entity.GetType().GetProperty(name);
if (property == null) continue;
property.SetValue(entity, value, null);
}
}- Sugerido como Resposta AndreAlvesLimaModerator sexta-feira, 7 de maio de 2010 23:23
- Marcado como Resposta AndreAlvesLimaModerator sexta-feira, 14 de maio de 2010 15:15
-
-
Alias... se for no 4.0 ja tem o metodo para isso:
context.ObjectStateManager.GetObjectStateEntry(entidade).ApplyOriginalValues(entidade);
What would Brian Boitano do ?
((2B || !2B) is Question) ?- Sugerido como Resposta AndreAlvesLimaModerator sexta-feira, 7 de maio de 2010 23:23
- Marcado como Resposta AndreAlvesLimaModerator sexta-feira, 14 de maio de 2010 15:15
-
poxa..bacana isso... agora vai fica melhro msm...
mais cara, vc trabalha com o EF2 correto? vc disse q deixa td num WS certo, mais como q fica para atualizar suas entidades que estao fora do contexto??aquela velha questao do attach que n funciona miuto bem ;(... tem como contornar isso de alguma forma mais elegante... oq eu faço eh copiar a entity key e logo as propriedades para assim fazer o update sem precisa ir na base ...
Ozzyvegeta -
Entao... nos meus WS quando eu recebo a Entidade via paramentro no meu webmethod ela ja vem desattachada bunitinha como tem que ser e o Attach ____ numa boa... eu so do um:
if (this.EntityState == System.Data.EntityState.Detached) context.Attach(this); para caso eu teje chamando o metodo internalmente ....
mas enfim... volta a questao que ja falei noutro post aqui... EF é não ferramenta para sistema de altaperformance.... enquanto vc quiser escovar bites "nao indo desncessariamente ao banco" não é usando EF que vai fazer isso....
como eu uso webservice... meu acesso a dados fica centrado em 1 unico servidor... que aguenta muito... entao nao esquento com quantidade de acessos ao BD...
mesmo pq o Sql tem tanto poolings e caches internos... que nao perde performance em nada... mas enfim... eu gosto de ficar dando FirstOrDefault o tempo todo para verificar se o registro foi ou nao alterado por outro usuario antes de fazer qq processamento com a entidade q recebo no webmethod....
What would Brian Boitano do ?
((2B || !2B) is Question) ?- Sugerido como Resposta AndreAlvesLimaModerator sexta-feira, 7 de maio de 2010 23:23
- Marcado como Resposta AndreAlvesLimaModerator sexta-feira, 14 de maio de 2010 15:15