Можно написать объединение между Sql и DataTable, используя Linq? - PullRequest
0 голосов
/ 15 декабря 2010

У меня есть процесс, который извлекает информацию о клиенте из нескольких баз данных (MySql) на основе отметки времени. Я храню эти данные в DataTable. Таблица данных представляет обновления существующей информации о клиенте, а также новую информацию о клиенте.

Я хочу удалить любые дубликаты в целевой базе данных (SqlServer) на основе одного постоянного значения, CompanyID и CustomerID. Итак, я думал, что объединение даст мне RecordIDs дубликатов в целевой БД, передаст List<int> (или некоторый механизм сбора) методу DELETE.

Что у меня есть:

using (var context = new DataContext(SqlConnection))
{
    var tblSource = context.GetTable<tblCustomerInfo>();
    var dupeIDs = from currCust in tblSource
                  join newCust in myTable.AsEnumerable() on currCust.CompanyID equals newCust.Field<string>("CompanyID")
                  where currCust.CustomerID.Equals(newCust.Field<int>("CustomerID")
                  select currCust.RecordID;
}

Это, очевидно, не работает. Я обновлю с точными сообщениями об ошибках немного, но это не компилируется.

Во-первых, правильный ли синтаксис соединения для того, чего я хочу достичь?

Во-вторых, как мне написать этот Linq для соединения между DataTable и базой данных SqlServer назначения?

Запоздалая мысль - возможно ли, если у меня есть коллекция двойных RecordID, использовать Linq для УДАЛЕНИЯ записей из целевой базы данных?

Редактировать Чтобы прояснить этот процесс, у меня есть входящие таблицы данных, подобные приведенным в DataSet:

Table1
CompanyID    CustomerID    Field1    Field2    ....
   1             5          ...       ...
   1             15         ...       ...

Table2
CompanyID    CustomerID    Field1    Field2    ....
   10           125         ...       ...
   10           145         ...       ...

Все это войдет в одну базу данных:

Destination DB  
CompanyID    CustomerID    Field1    Field2    ....   
   1              5          ...       ...  
   1              15         ...       ...    
   1              27         ...       ... 
   5              15         ...       ... 
   10             125        ...       ...
   10             145        ...       ... 
   11             100        ...       ...

Таким образом, в этом случае я бы удалил из таблицы назначения элементы, которые соответствуют таблицам 1 и 2. База данных назначения будет постоянно расти, поэтому создание списка CustomerID не представляется возможным. Тем не менее, я ожидаю, что ежедневный импорт новой и обновленной информации о клиентах будет относительно небольшим (в сотнях, может быть, около 1000 записей).

Если я не могу написать одно соединение, какой другой метод для завершения этого процесса будет уместным? Я пытаюсь что-то понять, так как похоже, что я не могу смешивать Linq-to-Sql и Linq-to-Objects.

Можно ли каким-то образом сопоставить мою таблицу данных с картой данных сущности, tbl_CustomerInfo, заполнив неизменную в противном случае переменную, а затем выполнить объединение?

Обновление

Вот то, чего я достиг на данный момент, и я получил результаты, которые ожидаю от dupes:

using (DataContext context = new DataContext(SqlConnection)
{
    var custInfo = context.GetTable<tbl_CustomerInfo>();

    string compID = ImportCust.Rows[0]["CompanyID"].ToString();

    var imports = from cust in ImportCust.AsEnumerable()
                  select cust.Field<int>("CustomerID");

    var dupes = from cust in custInfo
                join import in imports
                on cust.CustomerID equals import
                where cust.CompanyID == compID
                select cust;

    custInfo.DeleteOnSubmit(/* what goes here */);
    context.SubmitChanges();
}

Мой вопрос сейчас таков: что входит в DeleteOnSubmit(...)? Я чувствую, что подобрался так близко, что меня это сорвало.

Ответы [ 3 ]

1 голос
/ 16 декабря 2010

Я обычно занимаюсь всем этим в сохраненном процессе для эффективности.

Добавьте поле идентификации в таблицу назначения, чтобы однозначно идентифицировать записи, а затем используйте запрос, подобный этому:

DELETE d
FROM DestinationTable d JOIN (
   Select CompanyID, CustomerID, Min(UniqueID) AS FirstRecID
    FROM DestinationTable
    GROUP BY CompanyID, CustomerID) u on u.CompanyID=d.CompanyID AND u.CustomerID=d.CustomerID
WHERE d.UniqueID <> u.FirstRecID
0 голосов
/ 16 декабря 2010

Вот что у меня работает:

using (DataContext context = new DataContext(SqlConnection)
{
    var custInfo = context.GetTable<tbl_CustomerInfo>();

    string compID = ImportCust.Rows[0]["CompanyID"].ToString();

    var imports = from cust in ImportCust.AsEnumerable()
                  select cust.Field<int>("CustomerID");

    var dupes = from import in imports
                join cust in custInfo
                on import equals cust.CustomerID 
                where cust.CompanyID== pivnum
                select cust;

    var records = dupes.GetEnumerator();

    while (records.MoveNext())
    { custInfo.DeleteOnSubmit(records.Current); }

    context.SubmitChanges();
}

Если есть более эффективный метод, меня интересуют варианты.

0 голосов
/ 15 декабря 2010

Кроме того, вы можете создать два списка List<int>, содержащих идентификаторы из ваших двух источников, а затем использовать оператор Intersect LINQ для поиска общих элементов.

List<int> a = new List<int>{1,2,3,4,5,6,8, 10};
List<int> b = new List<int>{1,2,99,5,6,8, 10};
var c= a.Intersect(b);  //returns the items common to both lists
...