Como modificar a chave primária de um registro utilizando LINQ 2 Entities?

02/12/2009

Amigos,

Gostaria de atualizar a chave primária de um registro utilizando Linq 2 Entities.
Quando eu faço update via SQL Server Manager, atualizo corretamente o registro, mas quando tento via linq ele diz que não pode atualizar pois a propriedade código faz parte da chave e não pode ser modificada.

Vou passar o script da tabela, e depois meu método de update pra análise:

USE [CONSTRUSYS]
GO

/****** Object:  Table [Fiscal].[OrigemIcms]    Script Date: 12/02/2009 17:46:06 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [Fiscal].[OrigemIcms](
    [codigo] [int] NOT NULL,
    [descricao] [varchar](50) NOT NULL,
 CONSTRAINT [PK_origemIcms] PRIMARY KEY CLUSTERED
(
    [codigo] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING ON
GO




Método de update:

//Altera um registro existente na tabela OrigemICMS
        public void updateOrigemICMS()
        {
            try
            {
                Entities db = new Entities();
                var upOrigemICMS = (from p in db.OrigemIcms
                                    where p.codigo == staticCodigo
                                    select p).First();

                //Implantar mudança de PK
                upOrigemICMS.codigo = this.codigo;
                upOrigemICMS.descricao = this.descricao;

                db.SaveChanges();
                MessageBox.Show(ClassMessages.SucessUpdate);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ClassMessages.ErrorUpdate
                               + ex.Message,
                               "Alterar Origem ICMS");
            }
        }



Daniel Vieira

Daniel Vieira

Curtidas 0

Respostas

Luiz Maia

Luiz Maia

02/12/2009

Amigo,   Pq este codigo não é um auto incremento? Tem alguma restrição quando a isto?   Aguardo Att Luiz Maia
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009

Sim, são os códigos dos impostos do governo.
Por exemplo, a CST, posso ter os valores:

00
10
20
30
40
41
50
51
70
99

etc...

Quem define é o governo, eu vou gerar as telas para o dpto fiscal fazer o cadastro, e se o governo cria um novo, ou altera um exitente, eles possam alterar.
GOSTEI 0
Luiz Maia

Luiz Maia

02/12/2009

Me mande o erro que esta acontecendo por favor Luiz Maia
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009


A primeira linha é um texto default feito por mim, a segunda é a exception gerada pelo framework


GOSTEI 0
Luiz Maia

Luiz Maia

02/12/2009

Daniel, ja não tivemos este mesmo problema ha tempos atras e foi solucionado?   Veja: https://www.devmedia.com.br/suporte/viewtopic.asp?id=11004   Caso seja alguma coisa diferente disto, me diga, ok? Aguardo   Att Luiz Maia
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009

Luiz, se prestar atenção aquele chamado que eu abri era pra update em chave FK, chave estrangeira.

Esse é pra chave primária PK. Eu tentei e não funcionou com o mesmo método da chave estrangeira.
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009

Luiz, aquele chamado que eu abri era pra update em chave FK, chave estrangeira.

Esse é pra chave primária PK. Eu tentei e não funcionou com o mesmo método da chave estrangeira.
GOSTEI 0
Luiz Maia

Luiz Maia

02/12/2009

Daniel,   Desculpe a demora, pois eu tive que desenvolver um projeto similar para eu solucionar. Criei um entidade chamada Atividade, que tem o ID como PK. Veja no codigo abaixo que atualizo o campo ID, o qual eu recupero o registro em questão usando Lambda. Funcionou perfeitamente, veja se consegue esta implementação ai.     public static void Salvar(Entity.Atividade dbAtividade) { Entity.DataClassesDataContext dataClass = new Entity.DataClassesDataContext(); //Verifica se ‚ para atualiza‡Æo da pessoa ou novo plano de a‡Æo if (dbAtividade.Id != 0) { //Busca a organiza‡Æo pelo c¢digo informado para atualizar o registro var Atividade = dataClass.Atividades.Single(pa => pa.Id == dbAtividade.Id); //Autalizando valores do registro retornado com os valores passados Atividade.Id = dbAtividade.Id; Atividade.IdTipoAtividade = dbAtividade.IdTipoAtividade; Atividade.IdPessoa = dbAtividade.IdPessoa; Atividade.IdStatusAtividade = dbAtividade.IdStatusAtividade; Atividade.NomeAtividade = dbAtividade.NomeAtividade; Atividade.DscPorque = dbAtividade.DscPorque; Atividade.DscComo = dbAtividade.DscComo; Atividade.DscOnde = dbAtividade.DscOnde; Atividade.DscObservacao = dbAtividade.DscObservacao; Atividade.DscOrcamento = dbAtividade.DscOrcamento; dataClass.SubmitChanges(); } else { dataClass.Atividades.InsertOnSubmit(dbAtividade); dataClass.SubmitChanges(); } }   Aguardo seu retorno Daniel. Abraços Att Luiz Maia
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009

Luiz,

Meu Model não reconhece o método

db.SubmitChanges();

Vou testar com o que eu estou acostumado a usar e funciona, o

db.SaveChanges();

vamos ver se roda!
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009

Meu Model não reconheceu o método submitChanges, e também não reconheceu na expressão lambda o metodo .Single
A propria exception disse que não existe o metodo Single no Linq to Entities, e disse pra usar o metodo first(o que eu utilizo normalmente)

Ficou definido da seguinte maneira:

try
            {
                Entities db = new Entities();

                var upOrigemICMS = db.OrigemIcms.First(pa => pa.codigo == staticCodigo);


                upOrigemICMS.codigo = this.codigo;

                upOrigemICMS.descricao = this.descricao;

                db.SaveChanges();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ClassMessages.ErrorUpdate
                               + ex.Message,
                               "Alterar Origem ICMS");
            }


Acabou gerando o mesmo erro, da primeira vez, mas analisando o codigo, ficou identico ao meu metodo de alteracao, exceto a query, agora esta usando expressao lambda...
Eu estou usando L2E

Sera que voce nao utilizou outra metodologia de acesso a dados?
GOSTEI 0
Luiz Maia

Luiz Maia

02/12/2009

Sim, me desculpe, acho que usei L2Sql. Vou refazer usando L2E e te mando novamente.   Abraços Att Luiz Maia
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009

tranquilo fico no aguardo Luiz
GOSTEI 0
Luiz Maia

Luiz Maia

02/12/2009

Daniel,   Apos um boa pesquisada descobri que não há como alterar um PK no L2E. De acordo com a propria MS, alterar PK ja não é uma regra praticavel, ou seja, nunca se deve faze-la. Isto não é somente regras do L2e e sim uma regra de persistencia de DataBAse. Outra coisa é que o L2E usa Refletion e como nao tera a referencia antiga, não tem como alterar as novas.   Como não conheço suas regras de negocio, e se realmente não houver outra forma de fazer o que quer sem alterar a PK, sugiro que faça uma Stored Procedure a invoque a mesma usando L2E.   Abraços Att Luiz Maia    
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009

Caramba Luiz, não gostei dessa regra do L2E... Se o próprio SQL Server me permite, porque minha aplicação quer sobrepor a integridade do meu banco? Se for assim eu vou utilizar arquivos txt pra armazenagem, e deixar a aplicação tomar conta de toda a integridade!!

Hehe, desculpe a revolta, mas é que vou ter que modificar a estrutura do meu projeto agora...
Vou ver com o Analista se posso criar uma pk identity, e deixar o codigo como um campo comum, mas o problema é que eles precisam ser fk de outras tabelas, não vai dar certo...

Eu ainda não utilizei sp no L2E, voce poderia me dar um exemplo basico, pra finalizarmos o chamado?
GOSTEI 0
Luiz Maia

Luiz Maia

02/12/2009

Daniel,   Se vc criar um PK identity, ai que você não vai conseguir alterar mesmo. A unica forma é criar um campo sem ser identity e sem PK, mas acredito que isto o seu DBA não vai concordar.   Para usar um SP no Linq, vc primeiro precisa mapea-la. Pa isto use a Function Import: NO seu arquivo .edmx, botão direito e depois Add > Function IMport.   Segue o exemplo de L2E com SP usando o Nortwind:   set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go


ALTER PROCEDURE [dbo].[CustOrdersOrders] @CustomerID nchar(5)
AS
SELECT *
FROM Orders
WHERE CustomerID = @CustomerID
ORDER BY OrderID     E no codigo:   var db =new NorthwindEntities();
var v=db.CustomerOrders("ALFKI");     So uma dica, dentro da SP vc pode criar uma Tabela temporaria, que sera populada com os dados que precisa, sem se importar com PK, depois vc importa os dados da #tabela para a tabela real.     Abraços Att Luiz Maia    
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009

Acho que não vou escapar da SP mesmo... porque o banco aceita modificação da pk.

Mas eu sinto até arrepios de utilizar SP no projeto, principalmente porque:

1-Altero a estrutura da minha tabela, a SP não funciona corretamente.
2-Altero a estrutura da minha tela, a SP não funciona corretamente.
3-Altero a SP, a minha tela não funciona mais corretamente.

Tenho que correr com os 2 redondos, pra tudo funcionar legal. Com uma equipe reduzida ainda dá pra levar tranquilo (nossa equipa são 2 desenvolvedores). Mas quando a equipe aumenta a coisa começa a fugir do controle...E temos contratação em vista, a curto e médio prazo.

Eu sinceramente não gosto de SP no projeto, e sinceramente não gosto de projetos com LN no banco, pra mim banco serve pra armazenar dados, e isso já é uma grande tarefa...

Mas pra esse caso, não vemos outra saída, correto?

GOSTEI 0
Luiz Maia

Luiz Maia

02/12/2009

Daniel,   Se seu projeto for bem documentado, não vejo problema nenhum em usar SP, trabalho em Banco e aqui muita regra de negocio é dentro do SQL.   Mas caso queira outra solução, me avise que daremos um jeito de achar a melhor modelagem para seu projeto.   Abraços Att Luiz Maia
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009

Então Luís, a documentação aqui não é a prioridade do sistema (querem o quanto antes, melhor fazer mais telas que documentar o que existe).
Podemos pensar em outra maneira que não seja SP interagindo diretamente com o programa?
Eu prefiro fazer algo via VS do que via SQL Server.
GOSTEI 0
Luiz Maia

Luiz Maia

02/12/2009

Daniel,   Não tem como fugir de banco de dados. Outra solução seria uma tabela sem PKs que vc popularia esta tabela e depois faria uma sincronização, esta tabela não deve ter nem constraints. Isto supri suas necessidades?     Att Luiz Maia
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009

Eh luiz, vamos ter que partir pra SP mesmo, porque eu preciso ter pk nas tabelas, já que elas são referenciadas na montagem de um perfil fiscal.
Se eu não tiver a integridade vou ficar doido pra controlar via aplicação, pois são 11 tabelas auxiliares (todas elas essas na qual preciso atualizar o codigo PK)

Vamos partir pra cima das SP mesmo, vou implementar esse exemplo que você me passou e dou um feedback em seguida.
GOSTEI 0
Luiz Maia

Luiz Maia

02/12/2009

Ok Daniel, fico no aguardo.   Não se esqueça de modelar sua base muito bem modelada, colocando corretamente as constraints e relacionamentos, e principalmente, o tipo de integridade referencial cascata, pois ao alterar uma PK, deve alterar as FKs das outras tabelas.   De qualquer forma, acho estranho este comportamento! Vc tb pode usar umas triggers para garantir a integridade, ok?   Aguardo Abraços Att Luiz Maia  
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009

Mas em um curso de sql que eu fiz o consultor disse pra não utilizar Cascade.
Pois pode correr o risco de deletar um cliente e perder todos seus pedidos, seus itens, etc!
GOSTEI 0
Luiz Maia

Luiz Maia

02/12/2009

Daniel,   No seu caso não tem outro jeito. Tenho certeza que no curso de SQL que vc fez, seu instrutor tb lhe disse que não existe isto de alterar PKs. Mas ja que, pelo que me falou, o sistema exige que vc faça isto, não tem outro jeito, tem que ter cascate sim.   Imagine comigo uma hipotese bem simples, vc tem duas tabelas Produto e Categoria, por exemplo:   Cada produto tem uma categoria, por exemplo o Produto:   Liquidificador (PK = 1) tem a categoria Eletrodomestico (PK = 1).   Imagina vc alterar a PK da categoria de Eletrodomestico para 2, como ficaria a FK que agora esta igual a 1 na tabela Produto?   Vc tem q alterar tudo em cascata, para pelo menos, manter a consistencia de sua base, ok?   Abraços   Att Luiz Maia
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009

Agora sim Luiz, agora deu pra clarear tudo!

Se eu não setar como cascade, quando modificar a pk do codigo do imposto os perfis fiscais não receberão o novo valor, ficarão órfãos!

Realmente...

Mas eu tenho que ver aqui, porque a base está uma bagunça que só vendo... O DBA ta fazendo as tabelas tudo na hora, eu que deveria somente utilizar estou tendo que revisar, etc...Vou ver se agendamos uma reunião aqui, vou discutir todos esses pontos com o pessoal...

Sobre padronização de tabela, o que é mais legal?
Esse vai ser um dos tópicos que eu vou bater de frente... está tudo desorganizado aqui...
GOSTEI 0
Luiz Maia

Luiz Maia

02/12/2009

Daniel,   Não existe padronização de tabelas, cada empresa adota sua propria padronização e seus proprios minemonicos. Tenho um documento super confidencial, que posso te passar com padronizações usadas pela TelemigCelular, mas é confidencial, vc não podera usa-lo, somente basear nele, caso queira me avise que tenho que procurar aqui e te mando.   Abraços Att Luiz Maia
GOSTEI 0
Daniel Vieira

Daniel Vieira

02/12/2009

Eu agradeceria Luiz, porque assim como você disse, não existe padronização...Eu pesquisei na internet mas ninguém gosta de passar, assim como você disse, fica a cargo da empresa tomar conta.

E pode ficar tranquilo que eu não usarei o mesmo padrão não, somente teria um apoio pra fazer o meu, bem mais simplificado.

(Assim como utilizei aquela sua ajuda do projeto em 3 camadas que você me passou. Comecei o meu projetinho de certificação parecido com ele, mas enquanto o seu são 3 soluções em separado, o meu são 3 pastinhas dentro do mesmo projeto da solução. Mais simples mas utilizei a sua idéia.)
GOSTEI 0
Luiz Maia

Luiz Maia

02/12/2009

Daniel,   Segue o documento, http://video.devmedia.com.br/discovirtual/200237/Modelagem_Dados_Normas.zip     Não tem problema copiar, so não emita cópias do mesmo para outras pessoas, ok?   E quanto ao outro projeto que te passei, pode ficar a vontade para usa-lo.   Abraços Att Luiz Maia
GOSTEI 0
Devmedia

Devmedia

02/12/2009

Daniel,
podemos encerrar o chamado?
GOSTEI 0
POSTAR