Estou realmente lutando para fazer isso funcionar quando parece que deveria ser super simples.
Adicionei um cache à minha camada de serviço para dados retornados da EF.
Quando uma entidade é retornada do EF e atualizada, seu estado é EntityState.Modified
.
Quando é retornado do cache, seu estado é EntityState.Detached
, o que faz sentido.
Eu chamo DbContext.Update
se a entidade for Detached
e isso funciona bem para todas as propriedades que não sejam de navegação.
Para uma entidade rastreada, posso atualizar a propriedade FK ID diretamente, mas se ela começou desanexada, deve ser atualizada por meio da propriedade de navegação. O que, por algum motivo, também faz com que uma UPDATE
instrução seja executada para cada entidade relacionada, não apenas para a tabela muitos para muitos que eu esperaria.
Entidade rastreada:
// This will save to the DB
job.PrimaryAccountId = 123;
Entidade inicialmente destacada:
// This will NOT save to the DB
job.PrimaryAccountId = 123;
// This will not save to the DB
job.PrimaryAccount.AccountId = 123;
Atualize e salve após qualquer uma das opções acima:
await _dataAccess.Update(job);
await _dataAccess.SaveChangesAsync();
Esta operação deve ser considerada ilegal, portanto, fazer isso na instância em cache seria muito ruim se essa instância fosse rastreada.
Seu objetivo seria associar o trabalho a uma conta diferente, e não atualizar uma conta existente para alterar seu ID. (Se PK, isso não é permitido)
Lidar com entidades isoladas pode ser complicado. Lidar com gráficos de entidades desanexadas (entidades relacionadas) certamente ficará ainda mais confuso.
Se você carregou um trabalho e sua conta principal associada e desanexou essas referências em seu cache, anexá-las novamente causará problemas. Por exemplo, se eu fizer o seguinte:
... então armazenei isso em cache e algum código atualiza o trabalho:
Agora nós temos um problema. O Job possui uma propriedade de navegação apontando para a conta antiga, mas alteramos o FK do Job. Se quiser atualizar uma entidade desanexada, primeiro você precisa remover quaisquer referências de propriedade de navegação antes de chamar
Update
:.. A partir daqui você pode ligar para:
No entanto, se você precisar/quiser a conta associada na cópia em cache, será necessário buscar novamente as entidades associadas para atualizar a entrada de trabalho em cache.
Em última análise, não recomendo armazenar entidades em cache externamente, mas sim carregar entidades sob demanda e atualizar suas referências rastreadas. O cache apresenta mais problemas do que parece resolver.
Update()
substituirá automaticamente todos os valores de uma entidade, não apenas os valores que mudam, e executará umaUPDATE
instrução mesmo que nada realmente tenha mudado. Você também está expondo o sistema a substituições de dados obsoletos ou exceções de simultaneidade mais frequentes.A justificativa para a introdução do cache é quase sempre evitar viagens extras de ida e volta ao banco de dados. Isto é certamente valioso para operações de leitura, mas não deve ser um fator para operações de atualização. A busca de uma única entidade, e até mesmo de seus dados relacionados, é muito rápida, ajuda a detectar e evitar substituições de dados obsoletos e torna a atualização eficiente por meio do rastreador de alterações, gerando uma instrução Update apenas para os valores que mudam, se alguma coisa realmente mudar.