您可以通过定义从基本上下文派生的两个上下文来实现您想要的。一种上下文使用DatabaseGeneratedOption.Identity 定义其键,另一种使用DatabaseGeneratedOption.None 定义其键。第一个将是您的常规应用程序的上下文。
这是可能的,因为 Guid 主键不是真正的标识列。它们只是具有默认约束的列,因此它们可以插入 值或带 值而无需设置identity_insert。
为了证明这是可行的,我使用了一个非常简单的类:
public class Planet
{
public Guid ID { get; set; }
public string Name { get; set; }
}
基本上下文:
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);
}
}
上下文子类:
public class GenerateKeyContext : BaseContext
{
public GenerateKeyContext(string conString)
: base(conString, DatabaseGeneratedOption.Identity)
{ }
}
public class InsertKeyContext : BaseContext
{
public InsertKeyContext(string conString)
: base(conString, DatabaseGeneratedOption.None)
{ }
}
我首先运行一些代码来创建和植入源数据库:
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();
}
还有一个目标数据库:
using (var context = new GenerateKeyContext(db2))
{
context.Database.Initialize(true);
}
最后,这是完成实际工作的代码:
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();
}
现在在两个数据库中,您将看到两条具有相同键值的记录。
您可能想知道:为什么我不能使用一个上下文类,并在有或没有Identity 选项的情况下构造它?这是因为 EF 只为上下文类型构建 EDM 模型一次并将其存储在 AppDomain 中。因此,您首先使用的选项将确定 EF 将用于您的上下文类的模型。