使用 Linq 对 SETS 执行 CRUD:如何?

发布于 2024-09-30 22:21:07 字数 899 浏览 8 评论 0原文

使用 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 似乎是唯一适用于本地集的方法,并且它似乎只比较单个字段。数据库表具有复合键。

在不改变组合键的情况下,有什么办法可以完成这些任务呢?

Using Linq, trying to select all records not in my local set fails:

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);

I need to do basic CRUD: delete from the db set when not in my local set, update where exists, and add new when not there.

I would normally do:

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 )

Easy enough I thought. However, .Contains seems to be the only method that works with local sets, and it only seems to compare a single field. The database table has composite keys.

Without changing the composite keys, is there any way to accomplish these tasks?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

难忘№最初的完美 2024-10-07 22:21:07

您必须实现如下所示的 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());

让我知道这是否能满足您的需要。

You'll have to implement a CategoryComparer like the following:

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();
    }
}

Then call 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());

Let me know if this gets you what you need.

奶茶白久 2024-10-07 22:21:07

恐怕我不清楚您正在谈论哪种 Contains 方法......但是使用组合键的通用解决方案是使用匿名类型创建单个值。

例如,如果您想在复合键上加入,您可以使用

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

Does that help?

It's not clear to me which Contains method you're talking about, I'm afraid... but a general solution to using composite keys is to make a single value using an anonymous type.

For example, if you want to join on compound keys, you might use

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

Does that help?

掐死时间 2024-10-07 22:21:07

这样做怎么样:

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 运算符。如果有帮助请告诉我。干杯。

What about doing this:

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;

This converts a composite key into a single array that allows you to use the Contains operator. Let me know if it helps. Cheers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文