使用< T>< T>Linq C#从ID匹配的另一个List对象中查找一个List对象中不匹配的行

qxsslcnc  于 2023-07-31  发布在  C#
关注(0)|答案(1)|浏览(148)

我有一个包含记录集的Excel文件,还有一个包含记录集的名为UserTable的数据库。我所做的是将两者都改为列表,并将两个记录与名为UserId的字段进行比较。
现在我想用list2(来自Excel工作表)更新list1(来自数据库的usertable)。如果UserId字段在两个列表中都匹配,而其他任何字段都不匹配,则必须在list1中更新。
我试了这个代码:

public void Update(List<UserTable> users, List<UserTable> mappeddata)
{
    var valuetoupdate = mappeddata.IntersectBy(users.Select(y => y.UserId), y => y.UserId, StringComparer.OrdinalIgnoreCase);

    var rowsToUpdate = valuetoupdate.Except(users, new UserTableEqualityComparer());
}

public class UserTableEqualityComparer : IEqualityComparer<UserTable>
{
    public bool Equals(UserTable x, UserTable y)
            {
                if (x == null || y == null)
                    return false;
                else 
                    return
                       (string.Equals(x.ManagerUserId, y.ManagerUserId,    StringComparison.OrdinalIgnoreCase) &&
                       string.Equals(x.Department, y.Department, StringComparison.OrdinalIgnoreCase) &&string.Equals(x.Title, y.Title, StringComparison.OrdinalIgnoreCase) &&string.Equals(x.Email, y.Email, StringComparison.OrdinalIgnoreCase) &&string.Equals(x.FirstName, y.FirstName, StringComparison.OrdinalIgnoreCase)&&string.Equals(x.LastName, y.LastName, StringComparison.OrdinalIgnoreCase)&&string.Equals(x.PersonId, y.PersonId, StringComparison.OrdinalIgnoreCase)&&string.Equals(x.SiteCode, y.SiteCode, StringComparison.OrdinalIgnoreCase)&&string.Equals(x.BusinessUnit, y.BusinessUnit, StringComparison.OrdinalIgnoreCase)&&string.Equals(x.Category, y.Category, StringComparison.OrdinalIgnoreCase));
                      // string.Equals(x.Status, y.Status, StringComparison.OrdinalIgnoreCase));
}

public int GetHashCode(UserTable obj)
{
    unchecked
    {
        int hash = 17;
        hash = hash * 23 + (obj.UserId?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.ManagerUserId?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.Department?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.Title?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.Email?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.FirstName?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.LastName?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.PersonId?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.SiteCode?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.BusinessUnit?.ToLower().GetHashCode() ?? 0);
        hash = hash * 23 + (obj.Category?.ToLower().GetHashCode() ?? 0);
        // hash = hash * 23 + (obj.Status?.ToLower().GetHashCode() ?? 0);

        return hash;
    }
}

字符串
谢谢你,谢谢

xyhw6mcr

xyhw6mcr1#

首先,我将源数据转换为字典:

List<UserTable> mappeddata = ...; 
var dict = mappeddata
   .GroupBy(t => t.UserId) // or .GroupBy(t => t.UserId, StringComparer.OrdinalIgnoreCase)
   .ToDictionary(g => g.Key, g => g.First()); // possibly need some logic to handle duplicates

字符串
如果你使用的是EF Core,一个选择是只依赖它的更改跟踪器(尽管它会执行区分大小写的比较):

var fromDb = _ctx.UserTable
    .Where(t => dict.Keys.Contains(t.UserId)) // no need to fetch all users, fetch only existing in the dictionary
    .ToList();
foreach (var ut in fromDb)
{
    var source = dict[ut.UserId];
    // ... map data
}
_ctx.SaveChanges(); // will update only data with changed values


EF Core应仅在数据实际发生更改时更新数据。
如果你需要使用不区分大小写的比较,我仍然不会使用比较器方法。

var toUpdate = fromDb
    .Where(t =>
    {
        var source = dict[t.UserId];
        return !string.Equals(t.ManagerUserId, source.ManagerUserId, StringComparison.OrdinalIgnoreCase)
               || !string.Equals(t.Department, source.Department, StringComparison.OrdinalIgnoreCase);
    });
foreach (var ut in toUpdate)
{
    var source = dict[ut.UserId];
    // ... map data
}


如果你想坚持管理2个列表,那么你可以稍微修改一下第二种方法:

var toUpdate = users
    .Where(t => dict.ContainsKey(t.UserId)) // filter out not present in the data
    .Where(t =>
    {
        var source = dict[t.UserId];
        return !string.Equals(t.ManagerUserId, source.ManagerUserId, StringComparison.OrdinalIgnoreCase)
               || !string.Equals(t.Department, source.Department, StringComparison.OrdinalIgnoreCase);
    })
    .ToList();

相关问题