实体框架(MySQL)-使用两个dbcontext将数据从一个数据库移动到另一个数据库

时间:2018-07-04 07:47:16

标签: mysql .net entity-framework

我使用Entity Framework 6和MySQL,尝试将数据从“生产”数据库表归档到“归档”数据库。我为每个数据库创建了两个DBContext。每个数据库都有相同的架构。

我可以使用以下代码将整个数据表从生产数据库移动到存档数据库:

using (MyDBContext archiveContext = 
MyDBContext.CreateEntitiesForSpecificDatabaseName("archive_db"))
using (MyDBContext prodContext = 
MyDBContext.CreateEntitiesForSpecificDatabaseName("prod_db"))
{
    if(prodContext.myTable.Any())
    {
        archiveContext.myTable.AddRange(prodContext.myTable.AsNoTracking());
        archiveContext.SaveChanges();
    }  
}

但是我不想存档整个表,我只希望存档早于某个日期的数据,因此我尝试了以下操作:

using (MyDBContext archiveContext = 
MyDBContext.CreateEntitiesForSpecificDatabaseName("archive_db"))
using (MyDBContext prodContext = 
MyDBContext.CreateEntitiesForSpecificDatabaseName("prod_db"))
{
    IQueryable<myTable> dataToArchive =
      from mt in prodContext.myTable
      where mt.date < DateTimeSixMonths
      select mt;

     archiveContext.myTable.AddRange(dataToArchive);
     archiveContext.SaveChanges();
}       

但我无法解决运行此命令时遇到的异常:

  

System.InvalidOperationException:'实体对象不能为   由IEntityChangeTracker的多个实例引用。”

它发生在这一行:

archiveContext.myTable.AddRange(dataToArchive); 

是否可以通过某种方式从“ dataToArchive”中删除跟踪

2 个答案:

答案 0 :(得分:0)

您是否尝试过在检索数据后处置第一个DataContext?像这样:

List<myTable> dataToArchive;

using (MyDBContext prodContext = 
        MyDBContext.CreateEntitiesForSpecificDatabaseName("prod_db"))
{

    dataToArchive = (from mt in prodContext.myTable
        where mt.date < DateTimeSixMonths
        select mt).ToList();
}

using (MyDBContext archiveContext = 
    MyDBContext.CreateEntitiesForSpecificDatabaseName("archive_db"))
{
    archiveContext.myTable.AddRange(dataToArchive);
    archiveContext.SaveChanges();
}

答案 1 :(得分:0)

使用EF管理归档数据并不理想,对于低至中等的数据量或可分离的分区(即3-6个月的分区大小),使用insert-select + delete可以在数据库级别更好地实现类似目的可以在数据库之间移动。

要使用EF(仅建议用于小型和非复杂域模型)执行此操作,您应该能够通过在读取上下文中禁用代理生成,加载数据AsNoTracking,然后将其添加到新的上下文DbSet。此示例不处理关联的实体,也不执行从产品DbSet中删除的操作。

using (MyDBContext prodContext = 
        MyDBContext.CreateEntitiesForSpecificDatabaseName("prod_db"))
{
    prodContext.Configuration.ProxyCreationEnabled = false;
    dataToArchive = prodContext.myTable.AsNoTracking()
        .Where(mt => mt.Date < DateTimeSixMonths);


    using (MyDBContext archiveContext = 
        MyDBContext.CreateEntitiesForSpecificDatabaseName("archive_db"))
    {
        archiveContext.myTable.AddRange(dataToArchive);
        archiveContext.SaveChanges();
    }
}