EF6 entity with DatabaseGeneratedOption.Identity Guid Id force insert my Id value

c# code-first database entity-framework entity-framework-6

Popular Answer

By establishing two contexts that originate from a basic context, you may fulfil your goals. One context lists these as its keys.DatabaseGeneratedOption.Identity the second one havingDatabaseGeneratedOption.None The first one is the context of your standard application.

Due to Guid primary keys not being true identity columns, this is conceivable. Since they are only columns with a default constraint, a value may be placed into any of them without having to set anything.identity_insert on.

I used a very basic lesson to show that this is effective:

public class Planet
{
    public Guid ID { get; set; }
    public string Name { get; set; }
}

The basic situation

public abstract class BaseContext : DbContext
{
    private readonly DatabaseGeneratedOption _databaseGeneratedOption;

    protected BaseContext(string conString, DatabaseGeneratedOption databaseGeneratedOption)
        : base(conString)
    {
        this._databaseGeneratedOption = databaseGeneratedOption;
    }

    public DbSet<Planet> Planets { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Planet>().HasKey(p => p.ID);
        modelBuilder.Entity<Planet>().Property(p => p.ID)
                    .HasDatabaseGeneratedOption(this._databaseGeneratedOption);
        base.OnModelCreating(modelBuilder);
    }
}

The context classes include:

public class GenerateKeyContext : BaseContext
{
    public GenerateKeyContext(string conString)
        : base(conString, DatabaseGeneratedOption.Identity)
    { }
}

public class InsertKeyContext : BaseContext
{
    public InsertKeyContext(string conString)
        : base(conString, DatabaseGeneratedOption.None)
    { }
}

To construct and seed the source database, I first execute the following code:

var db1 = @"Server=(localDB)\MSSQLLocalDB;Integrated Security=true;Database=GuidGen";
var db2 = @"Server=(localDB)\MSSQLLocalDB;Integrated Security=true;Database=GuidInsert";

// Set initializers:
// 1. just for testing.
Database.SetInitializer(new DropCreateDatabaseAlways<GenerateKeyContext>());
// 2. prevent model check.
Database.SetInitializer<InsertKeyContext>(null);

using (var context = new GenerateKeyContext(db1))
{
    var earth = new Planet { Name = "Earth", };
    var mars = new Planet { Name = "Mars", };
    context.Planets.Add(earth);
    context.Planets.Add(mars);

    context.SaveChanges();
}

Moreover, a target database

using (var context = new GenerateKeyContext(db2))
{
    context.Database.Initialize(true);
}

Finally, here is the code that actually does the task:

var planets = new List<UserQuery.Planet>();
using (var context = new GenerateKeyContext(db1))
{
    planets = context.Planets.AsNoTracking().ToList();
}
using (var context = new InsertKeyContext(db2))
{
    context.Planets.AddRange(planets);
    context.SaveChanges();
}

You will now see two entries with the same key values in both databases.

If you're wondering why you can't build a context class with or without theIdentity option? This is due to the fact that EF creates the EDM model for a context type just once and saves it in the AppDomain. Therefore, the model that EF uses for your context class will depend on whatever option you choose initially.

2
11/13/2017 7:12:03 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow