2010-11-05 4 views
0

Использование Linq, пытаясь выбрать все записи, не в моем локальном наборе не удается:Использование Linq для выполнения CRUD на SETS: как?

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, кажется, единственный метод, который работает с локальными наборами, и это только кажется, сравнивает одно поле. Таблица базы данных содержит составные ключи.

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

ответ

1

Вы должны реализовать 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

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

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

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

ли это помощь?

1

А что делать это:

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. Дайте мне знать, если это поможет. Приветствия.