ChristianG
ChristianG

Reputation: 15

Entity Framework: Explicity set Primary key Value

Is it possible to set a primary key value of your own choice ? I'm working with data from an API and i'd like the objects to have the same id in my database as they have originally.

For example, i have an object with these attributes:

_context = new ApplicationDbContext();

Object
{
  id = 1234,
  Name = "Pitbull",
  Owner = "Greg"
};

_context.saveChanges(Object);

id is the PK for object in the database. But, if i save this the id is discarded and the database creates it's own value.

Thanks for reading ! :)

Upvotes: 0

Views: 329

Answers (1)

Harald Coppoolse
Harald Coppoolse

Reputation: 30454

Yes there is.

The proper way to do this is to override your three DbContext.SaveChanges methods. In these methods you'll give the primary keys of all added objects an Id.

In the example below this is done in method GenerateIds:

public override int SaveChanges()
{
    GenerateIds();
    return base.SaveChanges();
}

public override Task<int> SaveChangesAsync()
{
    GenerateIds();
    return await base.SaveChangesAsync();
}

public override Task<int> SaveChangesAsync(CancellationToken cancellationToken)
{
    GenerateIds();
    return await base.SaveChangesAsync(cancellationToken);
}

private void GenerateIds()
{
    var addedEntries = this.ChangeTracker.Entries()
        .Where(e => e.State == EntityState.Added)
    foreach (var addedEntry in addedEntries)
    {
         ((IId)addedEntry.Entity).Id = this.CreateId();
    }
}

CreateId should create a unique Id.

One of the Id generators I use often is nuget package IDgen (by RobIII). It is simple to install and to use. It generates unique System.Int64 identifiers, which have the advantage of being much smaller than a GUID. It works even if you have generators for the same database on multiple servers. The method it uses is the method twitter uses to generate ids for all its servers

Code is a one liner. In your DbContext:

private static IdGen.IdGenerator idGenerator = new IdGen.IdGenerator(0);
private long CreatedId()
{
    return idGenerator.CreateId();
}

Upvotes: 1

Related Questions