3 votes

Répliquer une ligne entière dans Entity Framework Core

J'essaie de récupérer une ligne de la base de données, de modifier la valeur de certaines colonnes et de l'ajouter comme nouvelle ligne (Entity Framework Core),

Mais je reçois l'erreur suivante

Impossible d'insérer une valeur explicite pour la colonne d'identité dans la table 'Audit_Schedules' lorsque IDENTITY_INSERT est défini sur OFF.

Cette table a une clé primaire "ScheduleId"

Voici mon code

 AuditSchedules _schedules = new AuditSchedules();
 using (var ctx = new QuestionnaireEntities(_configuration))
                {
                    _schedules = ctx.AuditSchedules.Where(x => x.ScheduleId == model.ScheduleID).SingleOrDefault();
                    _schedules.StaffId = model.TransferedAuditorCode;
                    _schedules.StaffName = model.TransferedAuditorName;
                    _schedules.FromDate = _schedules.ToDate = Convert.ToDateTime(model.TransferedScheduleDate);
                    ctx.AuditSchedules.Add(_schedules);
                    ctx.SaveChanges();

                    _subschedules = ctx.AuditSubSchedule.Where(x => x.SubScheduleId == model.SubScheduleID).SingleOrDefault();
                    _subschedules.IsHoliDay = "Y";
                    _subschedules.HolidayType = model.HolidayType;
                    _subschedules.TransferedScheduleId = _schedules.ScheduleId.ToString();
                    ctx.AuditSubSchedule.Update(_subschedules);
                    ctx.SaveChanges();
                }

L'erreur s'invite

ctx.AuditSchedules.Add(_schedules);

J'ai d'abord pensé qu'il y avait un conflit dans la valeur de Schedule_ID et qu'il n'était pas possible d'ajouter une clé primaire dupliquée, mais Schedule_ID est un champ généré automatiquement et ce problème ne devrait pas se produire.

J'ai également essayé de lui donner une valeur différente

_schedules.ScheduleId = 0;

mais il ne s'insère pas . Comment puis-je répliquer une ligne avec quelques changements (je veux ajouter une nouvelle ligne mais avec des valeurs modifiées) ?

4voto

Ivan Stoev Points 1156

Le comportement de EF Core avec les valeurs générées automatiquement lors de l'insertion est différent de celui de EF6.

Tout d'abord, la propriété doit avoir une valeur par défaut ( 0 ) afin d'être généré automatiquement. Cela permet d'insérer des identités, ce qui n'était pas possible dans EF6.

Deuxièmement, l'entité ajoutée ne doit pas être déjà suivie par le contexte, car dans le cas contraire, le contexte conserve en interne l'information que la clé de l'entité a été définie et inclura la valeur (même si elle n'a pas été définie). 0 ) dans les INSERT ce qui provoque l'exception que vous rencontrez.

Pour atteindre l'objectif, avant en appelant le Add méthode :

Assurez-vous d'abord que l'entité n'est pas suivie en utilisant soit Requête sans suivi lors de son obtention

_schedules = ctx.AuditSchedules
    .AsNoTracking() // <--
    .Where(x => x.ScheduleId == model.ScheduleID)
    .SingleOrDefault();

ou en le détachant explicitement

ctx.Entry(_schedules).State = EntityState.Detached;

Puis réinitialiser le PK

_schedules.ScheduleId = 0;

Ils effectuent d'autres modifications et appellent finalement

ctx.AuditSchedules.Add(_schedules);

Cela fonctionnera pour les entités simples sans propriétés de navigation / FK. Pour les graphes d'entités complexes, il convient d'utiliser la requête "no tracking", puis de l'utiliser de la même manière que pour les graphes d'entités détachées.

0voto

Praneet Nadkar Points 690

L'erreur est simple, c'est parce que vous ajoutez l'identité insert en tant que partie de insert. S'il s'agit d'une identité, elle doit être générée automatiquement. Donc, soit vous désactivez l'insertion avant l'insertion, puis vous l'activez. Ou bien faites en sorte qu'il soit généré automatiquement.

Cette erreur sera la même si vous essayez d'insérer les mêmes données à partir du serveur SQL. Ce problème est essentiellement propagé à partir du serveur SQL.

Si vous ne souhaitez pas qu'un identifiant soit généré par la base de données, vous devez utiliser l'attribut DatabaseGenerated sur votre modèle, comme dans l'exemple suivant

[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ScheduleId {get;set;}

Si vous souhaitez que l'insert d'identité soit désactivé, vous pouvez essayer la technique suivante aquí

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X