C# 实体框架中数据从一个提供者到另一个提供者的实时传输

C# 实体框架中数据从一个提供者到另一个提供者的实时传输,c#,entity-framework,production-environment,C#,Entity Framework,Production Environment,如果已经有人问过这一点,我很抱歉,因为我正在努力寻找的术语与实体框架中的功能相冲突 我想做的是: 我想创建一个应用程序,在安装时允许用户使用1个数据库作为“试用”/“启动”数据库,即非生产数据库。这将允许用户试用应用程序,但不会有备份等。这绝不是一个“生产”数据库。例如,这可能是SQLite 当用户准备好后,他们可以单击“转换为生产”(或类似),并为其指定新数据库机器/数据库的目标。这将被视为“生产”环境。这可能是MySQL、SQLServer或。。如今EF与之相关的任何东西 问题是: EF是否

如果已经有人问过这一点,我很抱歉,因为我正在努力寻找的术语与实体框架中的功能相冲突

我想做的是: 我想创建一个应用程序,在安装时允许用户使用1个数据库作为“试用”/“启动”数据库,即非生产数据库。这将允许用户试用应用程序,但不会有备份等。这绝不是一个“生产”数据库。例如,这可能是SQLite

当用户准备好后,他们可以单击“转换为生产”(或类似),并为其指定新数据库机器/数据库的目标。这将被视为“生产”环境。这可能是MySQL、SQLServer或。。如今EF与之相关的任何东西

问题是: EF是否支持这种类型的迁移/实时数据传输?它是否需要另一个应用程序,您可以在其中配置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