Использование LINQ to SQL для копирования между базами данных - PullRequest
9 голосов
/ 15 мая 2009

Учитывая две базы данных идентичной схемы, есть ли какой-нибудь простой способ переносить записи между ними? Я использую 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...
  };
}

и вставка клонированного элемента. Если я только скопирую рассматриваемые поля, а не какие-либо ссылки, представляющие отношения таблиц, это работает нормально. Однако это немного скучно, и для того, чтобы сделать это, мне нужно вручную назначить каждое поле в методе Clone. Кто-нибудь может предложить какие-либо способы сделать это проще? Я хотел бы знать две вещи:

  1. Может ли LINQ to SQL сделать это проще,
  2. Есть ли хороший способ использования Reflection для создания мелкой копии, которая будет вставлена?

Большое спасибо!

Ответы [ 6 ]

3 голосов
/ 05 октября 2010

Попробуйте это

using (DCDest = new DBDataContext(DestConnStr))
{
    DCDest.Customers.InsertOnSubmit(customer.ToList());  //note the use of .ToList()
    DCDest.SubmitChanges();
}
3 голосов
/ 15 мая 2009

Вот способ поверхностного клонирования объектов LINQ (без первичного ключа): Копирование объектов Linq .

Можно использовать метамодель, если вы не используете атрибуты. Тогда все, что вам нужно, это 2 контекста данных (один источник, один пункт назначения).

В качестве альтернативы вы можете посмотреть SqlBulkCopy - см. Копирование из одной таблицы базы данных в другую C #

0 голосов
/ 15 мая 2009

Возможно, вы захотите использовать вместо этого класс SQLBulkCopy. Вы можете найти статью о проекте кода здесь: http://www.codeproject.com/KB/database/SqlBulkCopy.aspx. Это был бы более быстрый способ сделать это, но я предполагаю, что вам потребуется создавать запросы самостоятельно, а не позволять LINQ-to-SQL делать это.

0 голосов
/ 15 мая 2009

Я использую 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.

0 голосов
/ 15 мая 2009

Зачем использовать LINQ для этого? Когда вы можете использовать DTS в SQL Server, кажется, что фреймворк мешает работе инфраструктуры.

0 голосов
/ 15 мая 2009

Это чисто академическое упражнение?

Если нет, я бы серьезно подумал об использовании 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 при передаче данных между базами данных. [Текст ссылки] [1]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...