根据您的描述,我认为没有任何现成的东西可以支持这一点。您可以将 DbContext 映射到任一数据库,然后从评估 DbContext 获取和分离实体并将它们附加到生产数据库。
对于一个相对简单的模式/对象图,这将是相当直接的实现。
ICollection<Customer> customers = new List<Customer>();
using(var context = new AppDbContext(evalConnectionString))
{
customers = context.Customers.AsNoTracking().ToList();
}
using(var context = new AppDbContext(productionConnectionString))
{ // Assuming an empty database...
context.Customers.AddRange(customers);
}
虽然对于更复杂的模型,这可能需要一些工作,尤其是在处理现有查找/引用之类的事情时。如果您想将可能共享相同引用的对象移动到另一个对象,您需要在目标 DbContext 中查询现有亲属并在保存“父”实体之前替换它们。
ICollection<Order> orders = new List<Order>();
using(var context = new AppDbContext(evalConnectionString))
{
orders = context.Orders
.Include(x => x.Customer)
.AsNoTracking()
.ToList();
}
using(var context = new AppDbContext(productionConnectionString))
{
var customerIds = orders.Select(x => x.Customer.CustomerId)
.Distinct().ToList();
var existingCustomers = context.Customers
.Where(x => customerIds.Contains(x.CustomerId))
.ToList();
foreach(var order in orders)
{ // Assuming all customers were loaded
var existingCustomer = existingCustomers.SingleOrDefault(x => x.CustomerId == order.Customer.CustomerId);
if(existingCustomer != null)
order.Customer = existingCustomer;
else
existingCustomers.Add(order.Customer);
context.Orders.Add(order);
}
}
这是一个非常简单的示例,概述了如何处理可能插入数据的场景,其中引用可能存在或不存在于目标 DbContext 中。如果我们要跨订单复制并希望与他们各自的客户打交道,我们首先需要检查是否存在任何跟踪的客户参考,并使用该参考来避免插入重复的行或引发异常。
通常从一个 DbContext 加载订单和相关引用应确保引用同一客户实体的多个订单将共享同一实体引用。但是,要使用我们可以通过 AsNoTracking() 与新 DbContext 关联的分离实体,对同一记录的分离引用将不是相同的引用,因此我们需要小心处理这些。
例如,同一客户有 2 个订单:
var ordersA = context.Orders.Include(x => x.Customer).ToList();
Assert.AreSame(orders[0].Customer, orders[1].Customer); // Passes
var ordersB = context.Orders.Include(x => x.Customer).AsNoTracking().ToList();
Assert.AreSame(orders[0].Customer, orders[1].Customer); // Fails
即使在第二个示例中,两者都是针对同一客户的。每个都有一个具有相同 ID 的 Customer 引用,但有 2 个不同的引用,因为 DbContext 不跟踪所使用的引用。具有分离实体和努力提高性能等的几个“陷阱”之一。使用跟踪引用并不理想,因为这些实体仍会认为它们与另一个 DbContext 相关联。我们可以分离它们,但这意味着深入对象图并分离所有引用。 (可行,但与单独加载它们相比比较麻烦)
当可能批量迁移数据(定期处理 DbContext 以避免较大数据量的性能缺陷)或随着时间的推移同步数据时,它也会变得复杂。通常建议首先检查目标 DbContext 以查找匹配记录并使用这些记录来避免插入重复数据。 (或抛出异常)
如此简单的数据模型,这相当简单。对于更复杂的数据,需要带来更多数据以及数据之间的更多关系,情况会更加复杂。对于那些系统,我可能会考虑生成数据库到数据库的迁移,例如从源数据库中的数据为所需的目标数据库创建 INSERT 语句。只需按关系顺序插入数据以符合数据约束即可。 (使用工具或滚动您自己的脚本生成)