Fórum Como modificar a chave estrangeira de um registro utilizando Linq to Entities? #11004

03/11/2009

0

Amigos, boa tarde.

O cenário é o seguinte:

Tenho um registro de Produto que contém o seu código identity como chave primária.
Esse registro contém várias chaves estrangeiras, entre elas CódigoGrupo, CódigoGrupoSub, CódigoFamília.

Eu gostaria de fazer uma atualização em alguns registros, modificando as chaves estrangeiras apenas.

Ex:

Id         Descrição               Grupo         SubGrupo          Familia
1           Cimento                     1                  1                     1
2           Cal                             3                  2                     1
3           Tijolo                          4                  3                     4
4           Bloco                          1                  1                     9


Eu gostaria de reorganizar esses produtos, modificando seus Grupos, SubGrupos, Famílias.
Quando eu edito diretamente na base de dados (SQL Server 2008), o banco me deixa atualizar perfeitamente, apenas restringe se realmente existe os novos registros de Grupo, Subgrupo e Familia nas tabelas correspondentes.

Portanto eu posso passar de Grupo 6, SubGrupo 3, Familia 9 para Grupo 10 Subgrupo 10 Familia 10, desde que os segundos registros existam em suas tabelas respectivas.

Mas quando eu tento update via aplicação, utilizando Linq to Entities, eu obtenho a seguinte mensagem:

A propriedade 'codigoGrupoSubFamilia' faz parte das informações de chave do objeto e não pode ser modificada.

A mensagem vem em português mesmo, estou utilizando a versão traduzida do VS2008 e do SQL Server 2008 (que eu pessoalmente não gosto, mas a empresa optou pela versão traduzida).

Utilizando linguagem c#.

No aguardo, e se necessário posso postar scripts, métodos, código, qualquer coisa que seja necessária.

Daniel Vieira

Daniel Vieira

Responder

Posts

04/11/2009

Luiz Maia

Ola Andre, tudo bom?   Seguinte, temos tido muitas duvidas quanto ao L2E, e eu sempre que posso, recomendo NÃO usar, tem muita coisa errada ainda e de dificil implementação, mas como sempre, o pessoal fala que ja esta no meio do projeto e etc...   Mas é o seguinte, L2S é muito mais simples a estável, mas ja que esta usando L2E, faça o seguinte:     linq-to-entities record r = new record();
r.cityReference.EntityKey = new EntityKey("YourEntitiesNamespace.cities", "city_id", 5);  Exemplo acima: Note que o "record" tem a propriedade cityReference, que no seu caso sera familiaReference e assim por diante... Esta propriedade é automaticamente gerada edmx justamente por causa da referencia em outra entidade(table).   Este new EntityKey tem apenas 3 parametros: 1 - qualifiedEntitySetName(string): que sera o entityNameSpace.TableName. 2 - KeyName(string): campo da PK 3 - KeyValue(object): valor do campo PK   Espero ter ajudado. Aguardo seu retorno, ok?   Referencia: http://stackoverflow.com/questions/826537/how-do-i-update-an-objects-foreign-key-value-with-linq-to-entities   Abraços Att Luiz Maia 
Responder

Gostei + 0

04/11/2009

Daniel Vieira

record r = new record();
r.cityReference.EntityKey = new EntityKey("YourEntitiesNamespace.cities", "city_id", 5);  Exemplo acima: Note que o "record" tem a propriedade cityReference, que no seu caso sera familiaReference e assim por diante... Esta propriedade é automaticamente gerada edmx justamente por causa da referencia em outra entidade(table).   Este new EntityKey tem apenas 3 parametros: 1 - qualifiedEntitySetName(string): que sera o entityNameSpace.TableName. 2 - KeyName(string): campo da PK 3 - KeyValue(object): valor do campo PK

Eu utilizo o L2E exatamente pelo que você disse, estamos no meio do projeto, e o início do projeto foi adquirido de terceiros, nem tivemos opção.

A propriedade Reference eu utilizo Reference.Value pra atribuir a referencia da FK em um novo registro a ser gravado.

newProduto.GrupoSubFamiliaReference.Value = newGrupoSubFamilia;


Agora EntityKey eu nunca utilizei, e acabei não entendendo os parâmetros muito bem.

Poderia me dar um exemplo, utilizando a minha nomenclatura?

Tabela pai (que eu quero atualizar as fks)
Produto

Tabelas estrangeiras
Grupo
GrupoSub
GrupoSubFamilia

Digamos que eu quero atualizar o Campo codigoGrupoSubFamilia do registro de Produtos, de 3 para 1, qual seriam os parâmtros que eu teria que passar?



Responder

Gostei + 0

04/11/2009

Daniel Vieira


Eu utilizo o L2E exatamente pelo que você disse, estamos no meio do projeto, e o início do projeto foi adquirido de terceiros, nem tivemos opção.

A propriedade Reference eu utilizo Reference.Value pra atribuir a referencia da FK em um novo registro a ser gravado.

newProduto.GrupoSubFamiliaReference.Value = newGrupoSubFamilia;


Agora EntityKey eu nunca utilizei, e acabei não entendendo os parâmetros muito bem.

Poderia me dar um exemplo, utilizando a minha nomenclatura?

Tabela pai (que eu quero atualizar as fks)
Produto

Tabelas estrangeiras
Grupo
GrupoSub
GrupoSubFamilia

Digamos que eu quero atualizar o Campo codigoGrupoSubFamilia do registro de Produtos, de 3 para 1, qual seriam os parâmtros que eu teria que passar?



Responder

Gostei + 0

04/11/2009

Luiz Maia

Opa, seria algo assim:   int codigoGrupoSubFamilia = 1; //aqui seu novo valor a ser atualizado ok?   Produto.ProdutoIdreference.EntityKey = new EntityKey("SuaEntities.GrupoSubFamilia", "CodGrupoSubFamilia", codigoGrupoSubFamilia);   Lembrando: CodGrupoSubFamilia = PK da entidade Familia;     Aguardo... Abraços   Att Luiz Maia    
Responder

Gostei + 0

04/11/2009

Daniel Vieira

A pk da entidade família é composta, na verdade é uma cascata...

Pra esclarecer melhor vou postar a organização das tabelas:

tblGrupo
codigoGrupo
Descricao

tblGrupoSub
codigoGrupo FK
codigoGrupoSub
Descricao

tblFamilia
codigoGrupo FK
codigoGrupoSub FK
codigoGrupoSubFamilia
Descricao

tblProduto
codigoProduto
Descricao
codigoGrupo FK
codigoGrupoSub FK
codigoGrupoSubFamilia FK

Campos sublinhados são PK

Eu preciso trocar os valores das 3 FKs na tabela de produto.
Pra navegar entre os 3 valores eu tenho acesso apenas navegando Produto.GrupoSubFamilia

Pra trocar esses 3 valores como ficaria o exemplo?
Responder

Gostei + 0

04/11/2009

Luiz Maia

Andre, pelo que entendi, não é Chave Composta que vc tem ai. Sua modelagem me parece equivocada, pois não tem necessidade de vc ter codGrupo, e codSubGrupo na tabela Produto, pois so com o codigo da Familia, vc tera os outros. Ja que uma Familia pertence a um SubGrupo e um subGrupo pertence a um Grupo, correto?   Aguardo
Responder

Gostei + 0

04/11/2009

Daniel Vieira

Na verdade não.

Uma família número 1 pode pertencer ao Grupo 1 + SubGrupo 1, e pode também pertencer ao Grupo 1 + Subgrupo 2.

Ex

Grupo     GrupoSub        Familia
1               1                      1
1               2                      1
1               2                      2
1               2                      3

A chave é baseada na composição das chaves anteriores
Responder

Gostei + 0

04/11/2009

Daniel Vieira



Olha o MER pra ficar mais claro
Responder

Gostei + 0

04/11/2009

Luiz Maia

Andre, como esta seu mapeamento? Veja neste exemplo abaixo de Mestre-Detalhe:        
Responder

Gostei + 0

04/11/2009

Daniel Vieira

O mapeamento da GrupoSubFamilia parece estar correto.

Mas o da produto esta em branco, da uma olhada:


GrupoSubFamilia







Produto







Responder

Gostei + 0

04/11/2009

Luiz Maia

Realmente esta faltando algo, tente refazer o Mapeamento. Atente para a propriedade de Multiplicidade da figura que te mandei...  Aguardo seu retorno, ok?   Abraços Att Luiz Maia
Responder

Gostei + 0

04/11/2009

Daniel Vieira

Desculpe Luiz foi erro meu.
Eu cliquei diretamente na tabela, clicando no mapeamento ficaria assim:


Responder

Gostei + 0

04/11/2009

Daniel Vieira

Consegui atualizar a FK UnidadeMedida da tabela de produtos, utilizando o metodo:

transfProduto.UnidadeMedidaReference.EntityKey =new EntityKey(
                                                                                    "Entities.UnidadeMedida",
                                                                                    "codigoUnidadeMedida",
                                                                                    "L");

Quando eu tento atualizar as chaves de GrupoSubFamilia, utilizando

transfProduto.GrupoSubFamiliaReference.EntityKey = new EntityKey(
                                                                                    "ModelDB.GrupoSubFamilia",
                                                                                    "codigoGrupoSubFamilia",
                                                                                    codGrupoSubFamilia);

Eu recebo a seguinte mensagem:

A lista de pares chave-valor fornecida contém um número incorreto de entradas. Há 3 campos de chave definidos no tipo 'CONSTRUSYSModel.GrupoSubFamilia' mas 1 foram fornecidos.
Nom do parâmetro: value

A mensagem vem em português.

Deve ser porque estou passando apenas 1 das chaves, e ela é chave composta.Como eu passaria os outros valores?
Responder

Gostei + 0

04/11/2009

Luiz Maia

Andre, estamos evoluindo!!! rsrs Olha so, dei um olhada nas referencias da Microsoft para criar chaves compostas e descobri isto, veja se funciona:   using (AdventureWorksEntities advWorksContext =
    new AdventureWorksEntities())
{
    try
    {
        Object entity = null;
        IEnumerable<KeyValuePair<string, object>> entityKeyValues =
            new KeyValuePair<string, object>[] {
                new KeyValuePair<string, object>("SalesOrderID", 43680) };

        // Create the  key for a specific SalesOrderHeader object.
        EntityKey key = new EntityKey("AdventureWorksEntities.SalesOrderHeader", entityKeyValues);

        // Get the object from the context or the persisted store by its key.
        if (advWorksContext.TryGetObjectByKey(key, out entity))
        {
            Console.WriteLine("The requested " + entity.GetType().FullName +
                " object was found");
        }
        else
        {
            Console.WriteLine("An object with this key " +
                "could not be found.");
        }
    }
    catch (EntitySqlException ex)
    {
        Console.WriteLine(ex.ToString());
    }
}   Aqui a referencia completa da MS: http://msdn.microsoft.com/en-us/library/dd283138.aspx   Vaja que são criados pares de chaves no exemplo acima:  IEnumerable<KeyValuePair<string, object>> entityKeyValues =
            new KeyValuePair<string, object>[] {
                new KeyValuePair<string, object>("SalesOrderID", 43680) };
  Isto se deve a sobrecarga deste metodo existente no new EntityKey.   Aguardo Att Luiz Maia
Responder

Gostei + 0

04/11/2009

Daniel Vieira

então se eu q
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar