Использование Linq для выполнения CRUD на SET: как? - PullRequest
0 голосов
/ 05 ноября 2010

При использовании Linq попытка выбрать все записи, не входящие в мой локальный набор, завершается неудачей:

var localset = new List<Category>();
localset.Add( new Category { pk1 = 1, pk2 = 1, name = "one" } );
localset.Add( new Category { pk1 = 1, pk2 = 2, name = "two" } );

var dbCategories = dc.Categories;

var diff = dbCategories.Except(localset);

Мне нужно сделать базовый CRUD: удалить из набора БД, когда его нет в моем локальном наборе, обновить там, где существует, и добавить новое, если его там нет.

Я бы обычно делал:

delete from Category C where not exists
    ( select null from LocalSet L where C.pk1 = L.pk1 and C.pk2 = L.pk2 )

update Category set name = L.name
from LocalSet L
where L.pk1 = Category.pk1 and L.pk2 = Category.pk2

insert into Category (pk1, pk2, name)
select pk1, pk2, name
from LocalSet L
where not exists (
    select null from Category C where L.pk1 = C.pk1 and L.pk2 = C.pk2 )

Достаточно легко, подумал я. Тем не менее, .Contains, кажется, единственный метод, который работает с локальными наборами, и он, кажется, сравнивает только одно поле. Таблица базы данных имеет составные ключи.

Без изменения составных ключей, есть ли способ выполнить эти задачи?

Ответы [ 3 ]

1 голос
/ 05 ноября 2010

Как насчет этого:

var localset = new List<Category>();
localset.Add(new Category { pk1 = 1, pk2 = 1, name = "one" });
localset.Add(new Category { pk1 = 1, pk2 = 2, name = "two" });

var flattened = localset
    .Select(dd => dd.pk1 + "|" + dd.pk2 + "|" + dd.name)
    .ToArray();

var dbCategories = dc.Categories;

var diff = from c in dbCategories
           let x = c.pk1 + "|" + c.pk2 + "|" + c.name
           where !flattened.Contains(x)
           select c;

Преобразует составной ключ в один массив, который позволяет использовать оператор Contains.Дайте мне знать, если это поможет.Приветствия.

1 голос
/ 05 ноября 2010

Вам нужно будет реализовать CategoryComparer, как показано ниже:

public class CategoryComparer : IEqualityComparer<Category>
{
    public bool Equals(Category a, Category b)
    {
        bool result = false;
        if( a.pk1 == b.pk1 && a.pk2 == b.pk2 && a.name == b.name)
            result = true;
        return result;    
    }

    public int GetHashCode(Category category)
    {        
        if (Object.ReferenceEquals(category, null)) return 0;        
        return category.pk1.GetHashCode() ^ category.pk2.GetHashCode();
    }
}

Затем вызовите Enumerable.Except:

var localset = new List<Category>();
localset.Add( new Category { pk1 = 1, pk2 = 1, name = "one" } );
localset.Add( new Category { pk1 = 1, pk2 = 2, name = "two" } );

var diff = dc.Categories
             .AsEnumerable()
             .Except(localset, new CategoryComparer());

Дайте мне знать, если это вам чтонеобходимо.

1 голос
/ 05 ноября 2010

Мне не ясно, какой метод Contains, о котором вы говорите, я боюсь ... но общее решение для использования составных ключей состоит в том, чтобы создать одно значение с использованием анонимного типа.

Например, если вы хотите присоединиться к составным ключам, вы можете использовать

from x in xs
join y in ys on new { x.k1, x.k2 } equals new { y.k1, y.k2 }

Это помогает?

...