O objeto é reinserido no banco de dados imediatamente após a exclusão (dblinq)
-
23-09-2019 - |
Pergunta
Eu tenho um banco de dados MySQL, cuja estrutura geral se parece com a seguinte:
Manufacturer <== ProbeDefinition <== ImagingSettings
ElementSettings ====^ ^==== ProbeInstance
Estou usando o Innodb para permitir chaves estrangeiras e todas as chaves estrangeiras apontando para um ProbeDefinition
ter definido ON DELETE CASCADE
.
O problema que estou tendo é quando excluo um ProbeDefinition
No meu código, ele é imediatamente reinserido. A exclusão em cascata acontece corretamente para que outras tabelas sejam limpas, mas parece que o LINQ para SQL pode estar enviando uma inserção sem motivo. Verificando a propriedade Alteração no banco de dados mostra 1 exclusão e sem inserções.
Estou usando o seguinte pequeno código para executar o Excluir:
database.ProbeDefinition.DeleteOnSubmit(probe);
database.SubmitChanges();
Os logs no MySQL mostram os seguintes comandos sendo executados quando isso é executado:
BEGIN
use `wetscoprobes`; DELETE FROM wetscoprobes.probedefinition WHERE ID = 10
use `wetscoprobes`; INSERT INTO wetscoprobes.probedefinition (CenterFrequency, Elements, ID, IsPhased, ManufacturerID, Name, Pitch, Radius, ReverseElements) VALUES (9500000, 128, 10, 1, 6, 'Super Probe 2', 300, 0, 1)
COMMIT /* xid=2424 */
O que poderia causar isso desnecessário INSERT
? Observe que excluir um Manufacturer
Da mesma maneira, exclui corretamente, com o seguinte log:
BEGIN
use `wetscoprobes`; DELETE FROM wetscoprobes.manufacturer WHERE ID = 9
COMMIT /* xid=2668 */
Editar: Após mais testes, parece que isso só acontece depois que eu povoie uma caixa de listagem com uma lista de ProbeDefinition
s.
Tentei executar o código de exclusão acima antes e depois que o snippet seguinte foi executado:
var manufacturer = (Manufacturer)cbxManufacturer.SelectedItem;
var probes = manufacturer.ProbeDefinition;
foreach (var probe in probes)
{
cbxProbeModel.Items.Add(probe);
}
O objeto é excluído corretamente antes que o código do referido seja executado, mas a qualquer momento após esse ponto, ele executa uma inserção após a exclusão. Não gosta do fato de o objeto ser referenciado em algum lugar?
Aqui está o código que estou executando para testar a exclusão de uma definição da janela intermediária:
database.ProbeDefinition.DeleteOnSubmit(database.ProbeDefinition.Last())
database.SubmitChanges()
Solução
Acontece que existem problemas quando há várias referências ao seu objeto. Passando pela fonte do dblinq, aprendi que depois de um DELETE
está concluído, ele passa por todos os outros objetos "assistidos", procurando referências.
Nesse caso, tenho várias referências através da tabela database.ProbeDefinition
bem como através da referência do fabricante, manufacturer.ProbeDefinition
. Isso não é um problema até que eu tenha acessado objetos através dos dois métodos. Usando Remove
pode excluir a referência do fabricante, usando DeleteOnSubmit
excluirá o objeto da tabela. Se eu fizer um ou outro, a outra referência ainda existe e, portanto, o objeto está marcado para ser reinserido. Não tenho certeza se este é um bug no DBLINQ que ele não exclui outras referências ou comportamento esperado.
De qualquer forma, no meu caso, a solução é acessar a tabela usando apenas um método único e excluir usando esse método ou excluir usando os dois métodos. Para fazê -lo funcionar, usei o segundo método:
// Delete probe
this.manufacturer.ProbeDefinition.Remove(probe);
database.ProbeDefinition.DeleteOnSubmit(probe);
database.SubmitChanges();
EDITAR: Após mais trabalhos no projeto e questões semelhantes, encontrei a verdadeira questão subjacente da minha implementação. Eu tenho um datacontext de longa duração e, com o funcionamento do cache (para fazer os submitchanges funcionarem), você não pode fazer isso. o real A solução é ter um datacontext de curta duração e reconectar-se ao banco de dados em cada método.