EF, Code First - How to set a custom Guid identity value on insert

databasegeneratedoption
entity framework generate guid automatically
valuegeneratedonadd
ef core identity column
entity framework core guid primary key
databasegeneratedoption.identity ef core
entity framework code first auto increment primary key
ef core default value

I`m facing the following problem when dealing with inserting new entities in the DB that has Guid as primary keys - EF 5 with Code first approach.

I know there are a lot similar topics as I was roving for hours for this issue, but I couldn`t find topic with this problem.

As an example, my POCO class is:

public class EntityRole : IAdminModel
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

    [Required]
    [MaxLength(50)]
    public string Name { get; set; }

    [Required]
    [Display(Name = "Role code")]
    [MaxLength(20)]
    public string RoleCode { get; set; }

    [Display(Name = "Entities Assigned")]
    [InverseProperty("Role")]
    public List<Entity> Entities { get; set; }
}

RoleCode and Name are just text data, that is editable in the admin panel, so don`t consider those field names.

When adding new entity I don`t specify primary key values. So far so good, all works fine here. As a primary key field that requires value and has auto-generation of values, it is supposed not to always specify Id, but if I set a value, it should be kept (if identity insert is enabled).

But in some cases I want to specify a primary key value, for example for initial seeding of my DB with values. I need it for later processing - lets just say I need that specific Guid to be there. So if I have in my Configuration class:

// Initial data seed
protected override void Seed(WebPortalDbContext context)
{
    context.MenuItems.AddOrUpdate(
        m => m.Id,
        new EntityRole {Id = new Guid("268bf332-910e-4ea1-92f8-1ac0611f4c62"), Name = "Some name", RoleCode = "SN"},
    );
}

The Guid key setting goes not work even if I do a regular add:

using (var context = new MyDBContext())
{
    context.MenuItems.Add(
        new Entity() {Id = new Guid("<some guid>"), Name = "fooname" /*some other values*/}
    );

    context.SaveChanges();
}

What I have in the SQL Server trace is:

exec sp_executesql N'declare @generated_keys table([Id] uniqueidentifier)
insert [dbo].[EntityRoles]([Name], [RoleCode])
output inserted.[Id] into @generated_keys
values (@0, @1)
select t.[Id]
from @generated_keys as g join [dbo].[EntityRoles] as t on g.[Id] = t.[Id]
where @@ROWCOUNT > 0',N'@0 nvarchar(50),@1 nvarchar(20)',@0=N'Chief Captain',@1=N'CO1'

Here it is obvious that the new Guid value is just not sent from the EF SQL generator to the SQL Server, so the problem is in EF.

So I removed the DatabaseGeneratedOption.Identity attribute, then it is ok, but I lose the auto generation of the Id key, which does not work for me as it is very rare case.

The only solution from me for now:

I ended up is to overwrite the SaveChanges() method of the DBContext and modify all entities that have state to be added (I took the idea from here):

/// <summary> Custom processing when saving entities in changetracker </summary>
public override int SaveChanges()
{
    // recommended to explicitly set New Guid for appropriate entities -- http://msdn.microsoft.com/en-us/library/dd283139.aspx
    foreach (var entry in ChangeTracker.Entries().Where(e => e.State == EntityState.Added))
    {
        var t = entry.Entity.GetType();
        if (t.GetProperty("Id") == null)
            continue;

        var info = t.GetProperty("Id").GetCustomAttributes(typeof (DatabaseGeneratedAttribute), true).Cast<DatabaseGeneratedAttribute>();
        if (!info.Any() || info.Single().DatabaseGeneratedOption != DatabaseGeneratedOption.Identity)
        {
            if (t.GetProperty("Id").PropertyType == typeof(Guid) && (Guid)t.GetProperty("Id").GetValue(entry.Entity, null) == Guid.Empty)
                t.GetProperty("Id").SetValue(entry.Entity, Guid.NewGuid(), null);
        }
    }
    return base.SaveChanges();
}

In combination with this, all DatabaseGeneratedOption should be removed. All models has primary keys named "Id", following one of the best practice topics for naming conventions.

But this does not looks very elegant workaronud, because I thnk EF5 should be able to handle such cases. It works for Int identities if identity insert is on.

So does someone has an idea how to achieve better solution on the problem?

The simple way for you to do this since it is a GUID is to have one constructor in your class like

public EntityRole()
{
   Id = Guid.NewGuid();
}

and remove The database generated option or change it to DatabaseGeneratedOption.None.

Generated Values, How to configure value generation for properties when using Entity Framework Core. Documentation � Learn � Q&A � Code Samples int, long, or Guid are set up to have values generated for inserted entities, if a value isn't primary key in SQL Server is automatically set up to be an IDENTITY column. If you add an entity to the context that has a value assigned to the property, then EF will attempt to insert that value rather than generating a new one. A property is considered to have a value assigned if it is not assigned the CLR default value (null for string, 0 for int, Guid.Empty for Guid, etc.).

You can mark Id as virtual property. So in you project where you creating fake data you can have internal EntityRole with overriden Id and here you can remove DatabaseGeneratedOption.Identity attribute or change it on DatabaseGeneratedOption.None.

[SOLVED], public class BaseEntity { public BaseEntity() { if(Id==Guid. Add the corresponding alter column fluent code using Sql("") method in the Up� When you use a code-first approach using Entity Framework, you have full control over your user identity options. However when developers deal with bigger projects, they typically prefer to use a table-first approach in which they create the database, then consume the information in the API, and lastly shape it in a way that it makes sense on the front end.

Visual Studio 2017, C#, EntityFramework v6.0 allows you to override with a custom value by passing the value in on creation through your controller. it does not need to be defined in the model bc it is already defined within ApplicationUser.

private string DateGuid()
    {
        string pre = "Ugly Users 😍🤔🤣😂-";
        return pre + Guid.NewGuid();
    }

// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]    
public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser { Id = DateGuid() };
            var result = await UserManager.CreateAsync(user, model.Password);
...

Entity Framework: how to set the type of a column as uniqueidentifier , I use Entity Framework 6, code-first. You can use a custom value converter or leverage the built in Here's an example, sample code can be found here: Add a property called Id with type Guid and mask the base Id property by using the Map the stored procedure to the Insert function of the Entity e.g.:. As you know, EF creates an IDENTITY column in the database for all the id (key) properties of the entity, by default. So, the underlying database generates a value for this column on each insert command, e.g., SQL Server creates an integer IDENTITY column with identity seed and increment to 1.

DataAnnotations, Data Annotations - DatabaseGenerated Attribute in EF 6 & EF Core So, the underlying database generates a value for this column on each insert It can be identity, rowversion or GUID. This means that EF will create an IDENTITY column in the SQL Server Download EF 6 Code-First Demo Project from Github� The following code inserts two employees into the database. For the first, no value is assigned to Employee.EmploymentStarted property, so it remains set to the CLR default value for DateTime. For the second, we have set an explicit value of 1-Jan-2000.

How to make EF-Core use a Guid instead of String for its ID/Primary , You need custom ApplicationUser inherit from IdentityUser<TKey> and custom Role inherit from IdentityRole<TKey> public class� Entity Framework relies on every entity having a key value that is used for entity tracking. One convention of Code First is implicit key properties; Code First will look for a property named “Id”, or a combination of class name and “Id”, such as “BlogId”. This property will map to a primary key column in the database.

Gotcha inserting entities with explicit ID generated in database in , Yesterday I was rewriting some code from Entity Framework 6 to Entity In Entity Framework 6 you can create an entity and set the primary key the ID is generated in database (i.e. identity in MS SQL Server) the value will� In Entity Framework, when you have a primary key field such as Id or AuthorId which is mapped to IDENTITY column in the database, it works well when you insert data. In some cases, you might need to insert explicit values into a SQL Server IDENTITY column. To do so, you need to enable IDENTITY_INSERT before calling SaveChanges() manually.

Comments
  • We use EF 5 code-first, and just set the [Key] attribute on the key properties of our entities. Every time we add an entity whose key is not set, and then call context.SaveChanges(), the key is automatically generated and is available to us from the entity object. The major difference is that our keys are ints instead of Guids - not sure if that matters.
  • Yes, with ints it is working fine, cause I think it is requential in the DB and the SQL Server generates new Id for it
  • It looks fine for small amount of model classes, but in my issue is to simulate the database generated option and not doing this for all DB models. We have about 50 and is growing - for each of them I have to create constructors with 1 line for the Id. Another issues is that we are checking the Id when we are not it the DB context to determine if we have this model from the DB or it is just created and still not saved (for example in a helper class).
  • Basically I`ve been looking for other solutions but did not found better than the method with overriding SaveChanges as I showed in the question. It works fine for now and no issues on that if I have value in Id or not so I think to go with it for now. Thx anyway for the hint.