Home > Software design >  EF Core sending PK value on Insert
EF Core sending PK value on Insert

Time:02-01

I'm getting an error:

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

The SQL generated is:

INSERT INTO [ScheduleTransactionLink] ([Id], [CreatedByUserId], [CreatedDate], [Deleted], [LastUpdateDate], [LastUpdatedByUserId], [PaymentNumber], [ScheduleId])
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7);`

So obviously the issue is something related to passing in an Id value, and I have IDENTITY INSERT to on. But I'm not sending an Id.

My table is defined as:

internal class ScheduleTransactionLink : EntityAudit
{
    [Required, Key]
    public int Id { get; set; }

    [Required]
    public Schedule Schedule { get; set; }

    [Required]
    public Transaction Transaction { get; set; }

    [Required]
    public int PaymentNumber { get; set; }
}

Same as all my other tables. But only this bit of code is failing. As I can see, the generated SQL is sending 'Id'.

This only started happening after I added a navigational property to this table for a very complete query elsewhere.

  modelBuilder.Entity<Transaction>()
      .HasOne(x => x.ScheduleTransactionLink)
      .WithOne(t => t.Transaction)
      .HasForeignKey<ScheduleTransactionLink>();

An example of how I save my entity is here:

ScheduleTransactionLink link = new ScheduleTransactionLink
{
    CreatedByUserId = _jwt.UserId,
    CreatedDate = DateTime.UtcNow,
    PaymentNumber = paymentNumber,
    Schedule = schedule,
    Transaction = transaction
};

_context.ScheduleTransactionLink.Add(link);

var result = await _context.SaveChangesAsync();

It's on the SaveChangesAsync where it errors out.

I have also added this code to OnModelCreating:

modelBuilder.Entity<ScheduleTransactionLink>(entity =>
{
    entity.Property(e => e.Id).UseIdentityColumn();
});

Looking at the database, the table is created correctly:

CREATE TABLE [dbo].[ScheduleTransactionLink]
(
    [Id] [int] IDENTITY(1,1) NOT NULL,
    ....

How do I stop EF from sending the PK value?

CodePudding user response:

I suspect that EF isn't able to fully work out how your 1:1 entities relate. It looks like it's grasped that Transaction is the principal but i suspect it's trying to forge a relationship by putting the transaction ID into the ScheduleTransaction.Id - that's an independent PK in its own right, not an FK of transaction ID.. You might have to help it out some by doing:

internal class ScheduleTransactionLink : EntityAudit
{
    [ Key]
    public int Id { get; set; }

    [Required]
    public Schedule Schedule { get; set; }

    public int TransactionId { get; set; }
    [Required]
    public Transaction Transaction { get; set; }

    [Required]
    public int PaymentNumber { get; set; }
}
modelBuilder.Entity<Transaction>()
  .HasOne(x => x.ScheduleTransactionLink)
  .WithOne(t => t.Transaction)
  .HasForeignKey<ScheduleTransactionLink>(stl => stl.TransactionId);

It might work to not add a TransactionId and just:

modelBuilder.Entity<Transaction>()
  .HasOne(x => x.ScheduleTransactionLink)
  .WithOne(t => t.Transaction)
  .HasForeignKey<ScheduleTransactionLink>(stl => stl.Transaction); 

..but it's not something I've come across/can test atm and the docs for configuring 1:1s do specifically have the "int Id property and nominate it in the fluent" approach. Give it a test, and if it works/doesn't let me know and I'll amend the answer

  •  Tags:  
  • Related