Wednesday, October 30, 2019

Cannot insert explicit value for identity column in table 'Players' when IDENTITY_INSERT is set to OFF.

What are we to do about this error in Entity Framework Core implementations? Well, this might be an actual opportunity for me to provide some value with my blog as all of the Stack Overflow stuff I see just suggests decorating the field which cannot be written to with...

[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]

 
 

...but that does not get at what was going on for me. The problem lay in attempting to add children of a parent and the column in question was to hold the reference key to the parent. In my case the parent was a Player which looked like so:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace FluffyNothing.Core.Objects
{
   public class Player
   {
      [Key]
      [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
      public long PlayerId { get; set; }
      [Required]
      [MaxLength(15)]
      public string PlayerIp { get; set; }
      public virtual ICollection<Message> Messages { get; set; }
   }
}

 
 

The players have messages and the Message object looks like this:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace FluffyNothing.Core.Objects
{
   public class Message
   {
      [Key]
      [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
      public long MessageId { get; set; }
      [Required]
      [ForeignKey("PlayerId")]
      public Player Player { get; set; }
      [Required]
      public string Copy { get; set; }
      public DateTime Time { get; set; }
   }
}

 
 

Alright, the thing that threw the error looked like so:

public void WriteMessages(Message player1Message, Message player2Message)
{
   var optionsBuilder = new DbContextOptionsBuilder<PlayerContext>();
   using (var context = new PlayerContext(optionsBuilder.Options))
   {
      using (var transaction = context.Database.BeginTransaction())
      {
         context.Messages.Add(player1Message);
         context.Messages.Add(player2Message);
         context.SaveChanges();
         transaction.Commit();
      }
   }
}

 
 

I'm just trying to jam the messages in the database. That won't work. Instead I needed to query the parents and make an association to the parents. I did that like this:

public void WriteMessages(Message player1Message, Message player2Message)
{
   var optionsBuilder = new DbContextOptionsBuilder<PlayerContext>();
   using (var context = new PlayerContext(optionsBuilder.Options))
   {
      using (var transaction = context.Database.BeginTransaction())
      {
         List<Player> twoPlayers = context.Players.Where(p => p.PlayerId ==
               player1Message.Player.PlayerId || p.PlayerId ==
               player2Message.Player.PlayerId).ToList();
         foreach (Player player in twoPlayers)
         {
            if (player.Messages == null) player.Messages = new List<Message>();
            if (player.PlayerId == player1Message.Player.PlayerId)
            {
               player.Messages.Add(player1Message);
            }
            if (player.PlayerId == player2Message.Player.PlayerId)
            {
               player.Messages.Add(player2Message);
            }
         }
         context.SaveChanges();
         transaction.Commit();
      }
   }
}

No comments:

Post a Comment