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 stupide que je ne peux pas comprendre.
J'ai deux tables:
- Contact: Id (clé primaire), Value, ContactTypeId (clé étrangère à ContactType)
- ContactType: Id (clé primaire), Type (Maison, cellule, travail, etc.)
Entity Framework a créé les deux entités suivantes:
- Contact: Id, Value, ContactType (Propriété De Navigation)
- ContactType: Id, Type, Contact (Navigation Propriété)
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.
Ça a l'air si simple! Je ne comprends pas!
12 réponses
Ce problème se produit parce que vous référencez le même objet plus d'une fois. Ce n'est pas une limitation de EF, mais plutôt une fonction de sécurité pour vous assurer que vous n'insérez pas le même objet avec deux ID différents. Donc, pour réaliser ce que vous essayez de faire, il suffit de créer un nouvel objet et d'ajouter l'objet nouvellement créé à 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 la boucle corps.
Essayez ceci:
Contact contact = dbContext.Contacts.Single(c => c.contactTypeId == 1234);
contact.contactTypeId = 4;
dbContext.AddObject(contact);
dbContext.SaveChanges();
L'entité créée par le framework n'a pas de contact.Propriété ContactTypeId. Il l'a automatiquement supprimé et a créé L'association ContactType à l'intérieur de L'entité de Contact.
La façon de le faire fonctionner, comme vous l'avez suggéré, est de 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;
Essayez
contact.ContactType = differentContactType;
Ou
contact.ContactTypeId = 3;
Vous essayez de définir L'Id du ContactType (du Contact) sur 3.
Cela s'est produit lorsque j'éditais 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 c'est évidemment assez stupide) mais en substance cela causait l'erreur dans mon cas.
J'utilise EF 4.0 et WPF et j'ai eu un problème similaire, et .... trouvé le problème résolu (au moins pour moi) d'une manière très simple.
Parce que, comme vous, je pensais qu'il devait être simple de mettre à jour un champ dans une table (c'est-à-dire dans votre cas: Contact) qui est référencé par une clé étrangère d'une autre table (c'est-à-dire dans votre cas: ContactType).
Cependant, le Message D'erreur: ".... fait partie des informations clés de l'objet et ne peut pas être modifié." seulement apparaît lorsque vous essayez de mettre à jour une clé primaire (ce qui n'était pas du tout mon intention).
A regardé 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 fait une erreur stupide dans ma base de données), quand Visual Studio a généré automatiquement pour moi le DataModel de ma base de données, il a ajouté dans cette table même (Contact ), où je voulais mettre à jour le champ (ContactTypeID
) un deuxième PropertyRef
(deuxième ligne).
J'ai juste supprimé cette seconde PropertyRef
:
<PropertyRef Name="contactTypeID" />
Dans les deux cas, la magasin modèle et le modèle conceptuel et .... le problème 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é .... :-)
Par conséquent, bonne idée de vérifier le XML du datamodel pour vérifier que seul votre PK est répertorié comme PropertyRef
. A travaillé pour moi ... :-)
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, c'est-à-dire:
<Key>
<PropertyRef Name="ID" />
<PropertyRef Name="No" />
<PropertyRef Name="Code" />
</Key>
Et chaque fois que je fais une opération de mise à jour, il lève cette exception:
La propriété 'Code' fait partie des informations clés de l'objet et ne être modifié.
Solution: supprimer la table du diagramme EF et aller à votre DB ajouter une clé primaire sur la table qui crée un problème et ré-ajouter la table au diagramme EF c'est tout maintenant, il aura une seule clé, c'est-à-dire
<Key>
<PropertyRef Name="ID" />
</Key>
, Il existe deux types d'associations. Association indépendante où la clé associée ne ferait surface que comme propriété de navigation. Le Second est l'association de clés étrangères où la clé associée peut être modifiée à l'aide de la propriété de clé étrangère et 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;
/ / l'option générique fonctionne avec une clé étrangère et une association indépendante
contact.ContactReference.EntityKey = new EntityKey("container.contactset","contacttypeid",3);
Dans mon cas, je veux dupliquer l'objet, mais changer l'id, donc j'utilise ce
Common.DataContext.Detach(object);
Travailler comme un charme
Supprimer D'Abord ajouter ensuite
Pour de simples
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";
}
J'espère juste que cela aide quelqu'un d'autre, après avoir lutté pendant des heures avec cela parce que je savais que je n'étais pas en train de mettre à jour le PK et que j'avais définitivement un PK. J'avais la valeur PK databound à une barre de menu pour afficher la valeur PK actuelle et cela causait le problème.
Dans mon cas, je viens de mettre 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 ce
<PropertyRef Name="id" />
Cependant, si la clé primaire n'est pas définie, vous auriez
<PropertyRef Name="id" />
<PropertyRef Name="col1" />
<PropertyRef Name="col2" />
Notez que la réponse de Juergen Fink est un travail autour
Dans mon cas, je créais un objet déclaré et initialisé ensemble. Je viens d'initialiser dans le constructeur ou ce que vous pouvez initialiser l'objet si nécessaire.