I'm currently trying to use Npgsql (version 3.1.3) to insert a record into a table with a generated identity using the official documentation (Npgsql.org) . But I always get the error:
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
---> Npgsql.PostgresException (0x80004005): 428C9: cannot insert into column "mitteilung_id"
I have already found several questions about this topic, but they are either outdated (version 2 or lower) or do not work.
My project is structured as follows. The table definition looks like this:
CREATE TABLE mitteilung
(
mitteilung_id INTEGER GENERATED ALWAYS AS IDENTITY
CONSTRAINT mitteilung_pk
PRIMARY KEY,
betreff TEXT
CONSTRAINT mitteilung_nn_betreff
CHECK (betreff IS NOT NULL)
CONSTRAINT mitteilung_ck_length_betreff
CHECK (length(betreff) <= 100),
nachricht TEXT
CONSTRAINT mitteilung_ck_length_nachricht
CHECK (length(nachricht) <= 500)
CONSTRAINT mitteilung_nn_nachricht
CHECK (nachricht IS NOT NULL),
erfasst_am TIMESTAMP WITH TIME ZONE
CONSTRAINT mitteilung_nn_erfasst_am
CHECK (erfasst_am IS NOT NULL)
);
I have defined the entity as follows:
public class Mitteilung : ISlongooEntity
{
public int MitteilungId { get; set; }
...
I have also tried to add the following attributes to the ID property:
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
In the DB context I have tested the following settings to solve the problem.
modelBuilder.Entity<Mitteilung>()
.Property(b => b.MitteilungId)
.UseIdentityAlwaysColumn();
modelBuilder.Entity<Mitteilung>()
.Property(b => b.MitteilungId)
.Metadata.SetValueGenerationStrategy(NpgsqlValueGenerationStrategy.IdentityAlwaysColumn);
modelBuilder.Entity<Mitteilung>()
.Property(b => b.MitteilungId)
.Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore);
But no matter in which combination I use the settings, I get the above mentioned error message when trying to save an entity. I also don't quite understand why an attempt is made to update the ID at all when an update is made. What am I doing wrong?
public Mitteilung Save(Mitteilung obj)
{
var addedObj = Context.Mitteilungen.Add(obj);
// Context.Entry(obj).Property(x => x.MitteilungId).IsModified = false;
Context.SaveChanges();
return addedObj.Entity;
}
The code below does work correctly.
Note that EF Core will automatically detect that MitteilungId
is the primary key for Mitteilung
, and since it's an int, will set it up as GENERATED BY DEFAULT AS IDENTITY
. In other words, you don't need any of the fluent API calls - or the [Key]
or [DatabaseGenerated]
annotations - EF Core will set things up correctly by convention.
If, for some reason, you need to have GENERATED ALWAYS AS IDENTITY
(instead of BY DEFAULT
), then the fluent API call below can be used.
If you're still having an issue, can you please change the code sample below to produce the error?
class Program
{
static async Task Main(string[] args)
{
await using var ctx = new BlogContext();
await ctx.Database.EnsureDeletedAsync();
await ctx.Database.EnsureCreatedAsync();
ctx.Blogs.Add(new Mitteilung { Name = "foo" });
await ctx.SaveChangesAsync();
}
}
public class BlogContext : DbContext
{
public DbSet<Mitteilung> Blogs { get; set; }
static ILoggerFactory ContextLoggerFactory
=> LoggerFactory.Create(b => b.AddConsole().AddFilter("", LogLevel.Information));
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseNpgsql("...")
.EnableSensitiveDataLogging()
.UseLoggerFactory(ContextLoggerFactory);
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Mitteilung>()
.Property(b => b.MitteilungId)
.UseIdentityAlwaysColumn();
}
}
public class Mitteilung
{
public int MitteilungId { get; set; }
public string Name { get; set; }
}
User contributions licensed under CC BY-SA 3.0