web-dev-qa-db-fra.com

La propriété 'Id' fait partie des informations clés de l'objet et ne peut pas être modifiée

j'utilise Entity Framework 4.0 et j'ai un problème idiot que je n'arrive pas à comprendre.

J'ai deux tables:

  1. Contact: Id (clé primaire), Valeur, ContactTypeId (clé étrangère à ContactType)
  2. Type de contact: Id (clé primaire), Type (Maison, Cellule, Travail, etc.)

Entity Framework a créé les deux entités suivantes:

  1. Contact: Id, Value, ContactType (propriété de navigation)
  2. Type de contact: ID, type, contact (propriété de navigation)

J'utilise le code suivant pour obtenir le contact et mettre à jour le type de contact pour ce contact particulier:

Contact contact = dbContext.Contacts.Single(c => c.Id == 12345);
contact.ContactType.Id = 3;

Lève l'exception suivante: 

The property 'Id' is part of the object's key information and cannot be modified.

C'est tellement simple! Je ne comprends pas!

33
Caesar

L'entité créée par la structure ne possède pas de propriété contact.ContactTypeId. Il l'a automatiquement supprimé et a créé l'association ContactType à l'intérieur de l'entité Contact.

La façon de le faire fonctionner, comme vous l'avez suggéré, consiste à créer un objet ContactType en interrogeant la base de données et en l'affectant à contact.ContactType. Par exemple:

Contact contact = dbContext.Contacts.Single(c => c.Id == 12345);
ContactType contactType = dbContext.ContactType.Single(c => c.Id == 3);
contact.ContactType = contactType;
14
Caesar

Ce problème se produit car vous référencez le même objet plusieurs fois. Il ne s'agit pas d'une limitation d'EF, mais d'une fonction de sécurité permettant d'éviter que vous n'insériez le même objet avec deux ID différents. Vous devez donc créer un nouvel objet et ajouter le nouvel objet à la base de données.

** Ce problème se produit souvent à l'intérieur des boucles. Si vous utilisez une boucle while ou foreach, assurez-vous d'avoir le nouvel objet créé DANS le corps de la boucle.

essaye ça:

Contact contact = dbContext.Contacts.Single(c => c.contactTypeId == 1234);
contact.contactTypeId = 4;
dbContext.AddObject(contact);
dbContext.SaveChanges();
23
AL-Tamimi

Essayer

contact.ContactType = differentContactType;

ou

contact.ContactTypeId = 3;

Vous essayez de définir l'ID du type de contact (du contact) sur 3.

5
DaveShaw

Cela se produisait lorsque je modifiais des objets liés à partir de deux contextes distincts en même temps. Exemple:

DataContext ctxA = new DataContext();
DataContext ctxB = new DataContext();

Author orwell = new Author {Name = "George Orwell" };
ctxA.Add(orwell);
ctxB.Add(new Book {Name = "1984", Author = orwell});

ctxA.SaveChanges();
ctxB.SaveChanges();

Mon cas était un peu plus compliqué (car cela est évidemment assez stupide), mais en gros, cela était la cause de l'erreur dans mon cas.

3
gardarh

Un autre comportement étrange dans mon cas, j’ai une table sans clé primaire.EF crée lui-même une clé primaire composite en utilisant toutes les colonnes, à savoir:

 <Key>
        <PropertyRef Name="ID" />
        <PropertyRef Name="No" />
       <PropertyRef Name="Code" />
   </Key>

Et chaque fois que je fais une opération de mise à jour, cette exception lève: 

La propriété 'Code' fait partie des informations clés de l'objet et ne peut pas être modifié.

Solution: supprimez la table du diagramme EF et accédez à votre base de données, ajoutez la clé primaire sur la table qui crée le problème et rajoutez la table dans le diagramme EF.

<Key>
        <PropertyRef Name="ID" />
</Key>
2
Sameer

J'utilise EF 4.0 et WPF et j'ai eu un problème similaire, et .... Trouvé le problème qui l'a résolu (au moins pour moi) d'une manière très simple.

Parce que, comme vous, j’ai pensé que la mise à jour d’un champ dans une table (c'est-à-dire dans votre cas: Contact) devait être simple et référencée par une clé étrangère d'une autre table (par exemple, ContactType).

Toutefois, le message d'erreur: ".... fait partie des informations de clé de l'objet et ne peut pas être modifié." n'apparaît que lorsque vous essayez de mettre à jour une clé primaire (ce qui n'était pas du tout mon intention). 

A examiné de plus près le code XML de mon EntityModel et l’a trouvé:

<EntityType Name="Contact">
    <Key>
        <PropertyRef Name="ID" />
        <PropertyRef Name="contactTypeID" />   <!-- This second line caused my problem -->
    </Key>
    <Property Name="ID" Type="int" Nullable="false" />
    ...
    ...
</EntityType>

Pour une raison quelconque (peut-être que j'ai commis une erreur stupide dans ma base de données), lorsque Visual Studio a généré automatiquement le DataModel à partir de ma base de données, il l'a ajouté dans cette même table (Contact), où je voulais mettre à jour le champ (ContactTypeID ) a secondePropertyRef (deuxième ligne).

Je viens de supprimer cette seconde PropertyRef:

<PropertyRef Name="contactTypeID" />

dans les deux cas, le problème de {modèle de magasin} _ et de modèle conceptuel} _ et .... a été résolu :-) 

Par conséquent, reste comme:

<EntityType Name="Contact">
    <Key>
        <PropertyRef Name="ID" />
    </Key>
    <Property Name="ID" Type="int" Nullable="false" />
    ...
    ...
</EntityType>

Les mises à jour et les inserts fonctionnent maintenant comme un bébé .... :-)

Il est donc judicieux de vérifier le code XML du modèle de données pour vérifier que seul votre PK est répertorié en tant que PropertyRef. Travaillé pour moi ... :-)

2
Juergen Fink

Il existe deux types d'associations. Association indépendante dans laquelle la clé associée n'apparaîtrait que comme propriété de navigation. La deuxième est l'association de clé étrangère, la clé associée pouvant être modifiée à l'aide de la clé étrangère et de la propriété de navigation. Donc, vous pouvez faire ce qui suit.

// option 1 option générique

var contacttype = new ContactType{Id = 3};
db.ContactTypes.Attach(contacttype);
customer.ContactType = contacttype;

option 2 clé étrangère option

contact.ContactTypeId = 3;

// option générique fonctionne avec une clé étrangère et une association indépendante

contact.ContactReference.EntityKey = new EntityKey("container.contactset","contacttypeid",3);
1
zeeshanhirani

premier Supprimersuivant ajoute

pour simple

public static IEnumerable UserIntakeFoodEdit(FoodIntaked data)
        {
            DBContext db = new DBContext();
            var q = db.User_Food_UserIntakeFood.AsQueryable();
            var item = q.Where(f => f.PersonID == data.PersonID)
                  .Where(f => f.DateOfIntake == data.DateOfIntake)
                  .Where(f => f.MealTimeID == data.MealTimeIDOld)
                  .Where(f => f.NDB_No == data.NDB_No).FirstOrDefault();

            item.Amount = (decimal)data.Amount;
            item.WeightSeq = data.WeightSeq.ToString();
            item.TotalAmount = (decimal)data.TotalAmount;


            db.User_Food_UserIntakeFood.Remove(item);
            db.SaveChanges();

            item.MealTimeID = data.MealTimeID;//is key

            db.User_Food_UserIntakeFood.Add(item);
            db.SaveChanges();

            return "Edit";
        }
1
Hossein Hajizadeh

dans mon cas, je viens de définir la clé primaire à la table qui manquait, re fait le mappind edmx et cela a fonctionné lorsque vous avez la clé primaire tou aurait seulement cette

<PropertyRef Name="id" />

cependant, si la clé primaire n'est pas définie, vous devriez 

<PropertyRef Name="id" />
<PropertyRef Name="col1" />
<PropertyRef Name="col2" />

notez que la réponse de Juergen Fink est un moyen de contourner

1
Mehdi Benkirane

Dans mon cas, je veux dupliquer l'objet, mais changer l'ID, donc je l'utilise

Common.DataContext.Detach(object);

Travailler comme un charme

1
DanielGatti

Espérer que cela aide quelqu'un d'autre, après avoir lutté pendant des heures avec cela parce que je savais que je ne mettais pas à jour le PK et que j'avais un PK. La valeur de la PK liée à une barre de menus indiquait la valeur actuelle de la PK, ce qui était à l'origine du problème.

0
Tony Gorham

Dans mon cas, l'erreur apparaissait lorsque j'ai supprimé l'attribut KEY du champ ID.

// [Key]
public long Id { get; set; }

Il suffit donc de remettre l'attribut à sa place pour que tout fonctionne à nouveau!

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
0
Dr TJ