C# 实体框架中数据从一个提供者到另一个提供者的实时传输
如果已经有人问过这一点,我很抱歉,因为我正在努力寻找的术语与实体框架中的功能相冲突 我想做的是: 我想创建一个应用程序,在安装时允许用户使用1个数据库作为“试用”/“启动”数据库,即非生产数据库。这将允许用户试用应用程序,但不会有备份等。这绝不是一个“生产”数据库。例如,这可能是SQLite 当用户准备好后,他们可以单击“转换为生产”(或类似),并为其指定新数据库机器/数据库的目标。这将被视为“生产”环境。这可能是MySQL、SQLServer或。。如今EF与之相关的任何东西 问题是: EF是否支持这种类型的迁移/实时数据传输?它是否需要另一个应用程序,您可以在其中配置EF源和EF目的地,然后让它运行数据源到另一个数据源的转换/种子设定/填充过程 我为什么在这里问:C# 实体框架中数据从一个提供者到另一个提供者的实时传输,c#,entity-framework,production-environment,C#,Entity Framework,Production Environment,如果已经有人问过这一点,我很抱歉,因为我正在努力寻找的术语与实体框架中的功能相冲突 我想做的是: 我想创建一个应用程序,在安装时允许用户使用1个数据库作为“试用”/“启动”数据库,即非生产数据库。这将允许用户试用应用程序,但不会有备份等。这绝不是一个“生产”数据库。例如,这可能是SQLite 当用户准备好后,他们可以单击“转换为生产”(或类似),并为其指定新数据库机器/数据库的目标。这将被视为“生产”环境。这可能是MySQL、SQLServer或。。如今EF与之相关的任何东西 问题是: EF是否
我试图围绕这个主题进行搜索,但迁移/迁移会带来完全无关的主题,因此非常感谢您提供的任何帮助。从您描述的内容来看,我认为没有任何现成的支持。您可以将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);
}
即使在第二个示例中,这两个都是针对同一客户的。每个都有一个ID相同的客户引用,但有两个不同的引用,因为DbContext没有跟踪所使用的引用。其中一个“陷阱”是分离实体并努力提高性能等。使用跟踪引用并不理想,因为这些实体仍然会认为它们与另一个DbContext关联。我们可以拆离它们,但这意味着在对象图中跳转并拆离所有引用。(确实可以,但与仅将其分离加载相比,会比较混乱)
当可能成批迁移数据(定期处理DbContext以避免较大数据量的性能缺陷)或随着时间的推移同步数据时,它也会变得复杂。通常建议首先检查目标DbContext是否有匹配的记录,并使用这些记录来避免插入重复的数据。(或抛出异常)
所以简单的数据模型这是相当直接的。对于更复杂的系统来说,需要传递的数据越多,数据之间的关系也越多,这就越复杂。对于这些系统,我可能会考虑生成数据库到数据库的迁移,例如从源数据库中的数据为所需的目标数据库创建INSERT语句。在这里,只需要按照关系插入数据,以符合数据约束。(使用工具或滚动您自己的脚本生成)哇,感谢您提供了深入的答案。我只是把这看作是一个“我该怎么做”的问题,根本没有涉及到包含关系数据的问题。我认为可以将其放在一个单独的应用程序/工具中,使用源数据库和目标数据库上下文。。然后根据应用程序的结构,正确传输数据,例如:库存、付款类型/历史记录、订单、客户(以您的示例为例)。。但是它需要大量的测试来确保翻译是正确的!
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);
}
}
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