使用LINQ to SQL在数据库之间进行复制

时间:2009-05-15 11:05:32

标签: c# linq-to-sql

鉴于两个相同架构的数据库,有没有简单的方法在两者之间传输记录?我正在使用LINQ to SQL,因为我需要在此过程中执行一些额外的操作,并且使用表示我正在传输的记录的对象使这更容易。这是一个小规模的帮助应用程序,所以SSIS可能有点过分,SQLBulkCopy不允许我在途中轻松查询对象。

我想做的是:

public static void TransferCustomer
                     (DBDataContext DCSource, 
                      DBDataContext DCDest, 
                      int CustomerID)
{
  Customer customer;
  using (DCSource = new DBDataContext(SourceConnStr))
  {
    customer = DCSource.Customers
                       .Where(c => c.CustomerID == CustomerID)
                       .Single();
  }

  using (DCDest = new DBDataContext(DestConnStr))
  {
    DCDest.Customers.InsertOnSubmit(customer);
    DCDest.SubmitChanges();
  }
}

但是由于显而易见的原因,它会在消息中引发异常:

  

尝试附加或添加非新的实体,可能是从另一个DataContext加载的实体。这不受支持。

我可以通过像这样对象的浅表副本来解决这个问题:

public static Customer Clone(this Customer customer)
{
  return new Customer()
  {
    Name = customer.Name,
    Email = customer.Email
    etc...
  };
}

然后插入克隆的项目。如果我只复制有问题的字段,而不是任何表示表关系的引用,这可以正常工作。然而,它有点啰嗦,我正在做的方式需要我手动分配克隆方法中的每个字段。任何人都可以建议任何使这更容易的方法吗?我想知道的两件事是:

  1. LINQ to SQL能否以更简单的方式执行此操作,
  2. 有没有一种很好的方法可以使用Reflection制作一个可以插入的浅拷贝?
  3. 非常感谢!

6 个答案:

答案 0 :(得分:3)

这是浅层克隆LINQ对象(省略主键)的方法:Copy Linq Objects

如果您不使用属性,可以调整使用元模型。然后你需要的只是2个数据上下文(一个源,一个目的地)。

或者,您可以查看SqlBulkCopy - 请参阅Copy from one database table to another C#

答案 1 :(得分:3)

试试这个

using (DCDest = new DBDataContext(DestConnStr))
{
    DCDest.Customers.InsertOnSubmit(customer.ToList());  //note the use of .ToList()
    DCDest.SubmitChanges();
}

答案 2 :(得分:0)

这纯粹是学术活动吗?

如果不是,我会认真考虑使用SSIS:http://msdn.microsoft.com/en-us/library/ms141026.aspx,或者使Rhino ETL失败:http://ayende.com/Blog/archive/2008/01/16/Rhino-ETL-2.0.aspxfor在数据库之间传输数据。[link text] [1]

答案 3 :(得分:0)

为什么要使用LINQ来做到这一点?当你可以使用SQL Server的DTS时,框架似乎有点浪费。

答案 4 :(得分:0)

我使用DataContractCloner来分离LINQ-to-SQL实体:

/// <summary>
/// Serializes the entity to XML.
/// </summary>
/// <returns>String containing serialized entity.</returns>
public string Serialize()
{
    return DataContractCloner.Serialize<Organization>(this);
}

/// <summary>
/// Deserializes the entity from XML.
/// </summary>
/// <param name="xml">Serialized entity.</param>
/// <returns>Deserialized entity.</returns>
public static Organization Deserialize(string xml)
{
    return DataContractCloner.Deserialize<Organization>(xml);
}

所有LINQ-to-SQL实体都已经过注释,因此这会创建一个可附加的克隆,稍后您可以通过一些警告重新附加。首先,外键关系将被解析,因此您必须按依赖顺序插入,如果您有循环关系,则必须从模式中删除外键并在传输后重新应用。其次,LINQ-to-SQL不执行标识插入,因此如果您使用自动增量标识列,则在提交时会遇到问题。我没有成功强制DataContext启用身份插入,但是YMMV。

答案 5 :(得分:0)

您可能希望考虑使用SQLBulkCopy类。您可以在此处找到有关它的代码项目文章:http://www.codeproject.com/KB/database/SqlBulkCopy.aspx。这将是一种更快速的方法,但我想它会要求你自己创建查询而不是让LINQ-to-SQL这样做。