-1

我有以下表结构

ID  firstName  LastName  zip     Address

1   test1      test2     NULL    NULL
2   test1      test2     12345   MI

我需要根据提供的 ID 合并 2 个帐户(主要和次要)。例如,如果给我值 1(作为主要)和 2(作为次要)进行合并。

主帐户 (1) 有 NULL zip 和地址,所以我需要从辅助帐户 (2) 复制这些并更新。最终结果应该是

ID  firstName  LastName  zip     Address

1   test1      test2     12345   MI

有什么方法可以使用 Linq,或者可以推荐其他方法吗?

4

2 回答 2

1

尽管 LINQ 中没有本机合并运算符,但您有几个选择。

首先,创建自己的合并!

public Account Merge(Account one, Account two) {

    ret = new Account(){
        Field = one.Field??two.Field
        //Repeat for all fields
    };
}

然后使用(手写代码,不要介意语法错误)

var mergedResults = (from primary in primaryAccounts
                    join secondary in secondaryAccounts
                          on primary.Id equals secondary.Id
                    select new {Primary=primary, Secondary secondary})
                    .Select(x=>Merge(x.Primary,x.Secondary);

其次,在 LINQ 中进行合并

差别不大

var mergedResults = (from primary in primaryAccounts
                    join secondary in secondaryAccounts
                          on primary.Id equals secondary.Id
                    select new Account { Field = primary.Field??secondary.Field}; //Repeat for all fields
于 2013-03-28T21:00:51.240 回答
0

Mabe 和我的分机

 public interface IMerge<out T>
{
    IEnumerable<IMergeMatched<T>> Matched();

    IEnumerable<IMergeMatched<T>> Matched(Func<T, T, bool> predicate);

    IEnumerable<T> NotMatchedBySource();

    IEnumerable<T> NotMatchedBySource(Func<T, bool> predicate);

    IEnumerable<T> NotMatchedByTarget();

    IEnumerable<T> NotMatchedByTarget(Func<T, bool> predicate);
}

public interface IMergeMatched<out T>
{
    T Source { get; }

    T Target { get; }
}

public static class Enumerable
{
    public static IMerge<TSource> Merge<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> target,
                                             Func<TSource, TSource, bool> predicate)
    {
        return new Merge<TSource>(source, target, predicate);
    }
}

public class Merge<T> : IMerge<T>
{
    private readonly Func<T, T, bool> _predicate;
    private readonly IEnumerable<T> _source;
    private readonly IEnumerable<T> _target;
    private IEnumerable<IMergeMatched<T>> _matcheds;
    private IEnumerable<T> _notMatchedBySource;
    private IEnumerable<T> _notMatchedByTarget;

    public Merge(IEnumerable<T> source, IEnumerable<T> taget, Func<T, T, bool> predicate)
    {
        _source = source;
        _target = taget;
        _predicate = predicate;
    }

    public IEnumerable<IMergeMatched<T>> Matched()
    {
        if (_matcheds == null)
        {
            Analize();
        }
        return _matcheds;
    }

    public IEnumerable<IMergeMatched<T>> Matched(Func<T, T, bool> predicate)
    {
        return Matched()
            .Where(t => predicate.Invoke(t.Source, t.Target))
            .ToArray();
    }

    public IEnumerable<T> NotMatchedBySource()
    {
        if (_notMatchedBySource == null)
        {
            Analize();
        }
        return _notMatchedBySource;
    }

    public IEnumerable<T> NotMatchedBySource(Func<T, bool> predicate)
    {
        return NotMatchedBySource()
            .Where(predicate)
            .ToArray();
    }

    public IEnumerable<T> NotMatchedByTarget()
    {
        if (_notMatchedByTarget == null)
        {
            Analize();
        }
        return _notMatchedByTarget;
    }

    public IEnumerable<T> NotMatchedByTarget(Func<T, bool> predicate)
    {
        return NotMatchedByTarget()
            .Where(predicate)
            .ToArray();
    }

    private void Analize()
    {
        var macheds = new List<MergeMached<T>>();
        var notMachedBySource = new List<T>(_source);
        var notMachedByTarget = new List<T>(_target);

        foreach (var source in _source)
        {
            foreach (var target in _target)
            {
                var macth = _predicate.Invoke(source, target);
                if (!macth) continue;

                macheds.Add(new MergeMached<T>(source, target));
                notMachedBySource.Remove(source);
                notMachedByTarget.Remove(target);
            }
        }

        _matcheds = macheds.ToArray();
        _notMatchedBySource = notMachedBySource.ToArray();
        _notMatchedByTarget = notMachedByTarget.ToArray();
    }
}

public class MergeMached<T> : IMergeMatched<T>
{
    public MergeMached(T source, T target)
    {
        Source = source;
        Target = target;
    }

    public T Source { get; private set; }

    public T Target { get; private set; }
}

如何使用?

    [TestMethod]
    public void TestMerge()
    {
        var source = new List<MediaFolder>
            {
                new MediaFolder
                    {
                        Id = "Id1",
                        Name = "Name1",
                        Path = "Path1"
                    },
                new MediaFolder
                    {
                        Id = "Id2",
                        Name = "Name2",
                        Path = "Path2"
                    },
                new MediaFolder
                    {
                        Id = "Id3",
                        Name = "Name3",
                        Path = "Path3"
                    },
                new MediaFolder
                    {
                        Id = "Id4",
                        Name = "Name4",
                        Path = "Path4"
                    },
                new MediaFolder
                    {
                        Id = "Id5",
                        Name = "Name5",
                        Path = "Path5"
                    },
                new MediaFolder
                    {
                        Id = "Id6",
                        Name = "Name6",
                        Path = "Path6"
                    }
            };

        var target = new List<MediaFolder>
            {
                new MediaFolder
                    {
                        Id = "Id1",
                        Name = "Actualizado en el objeto",
                        Path = "Path1"
                    },
                    //Id2 eliminado
                new MediaFolder
                    {
                        Id = "Id3",
                        Name = "Name3",
                        Path = "Actualizado tambien"
                    },
                new MediaFolder
                    {
                        Id = "Id4",
                        Name = "Name4",
                        Path = "Path4"
                    },
                new MediaFolder
                    {
                        Id = "Id5",
                        Name = "Name5",
                        Path = "Path5"
                    },
                new MediaFolder
                    {
                        Id = "Id6",
                        Name = "Name6",
                        Path = "Path6"
                    },
                     new MediaFolder
                    {
                        Id = "Id7",
                        Name = "Nuevo Item 7",
                        Path = "Nuevo Item 7"
                    }
            };

        var merge = source.Merge(target, (x, y) => x.Id == y.Id);

        var toUpdate = merge.Matched((x, y) => x.Name != y.Name | x.Path != y.Path)
            .ToArray();

        var toDelete = merge.NotMatchedBySource();
        var toInsert = merge.NotMatchedByTarget();

        Assert.AreEqual(2, toUpdate.Count());
        Assert.IsTrue(toUpdate.Count(x => x.Source.Id == "Id1" & x.Target.Id == "Id1") > 0);
        Assert.IsTrue(toUpdate.Count(x => x.Source.Id == "Id3" & x.Target.Id == "Id3") > 0);

        Assert.AreEqual("Id7", toInsert.First().Id);
        Assert.AreEqual("Id2", toDelete.First().Id);
    }

    [TestMethod]
    public void TestMerge2()
    {
        var source = new List<CustomObject>
            {
                new CustomObject
                    {
                        Year = 2010,
                        Month = 6,
                        Value = 2
                    },
                new CustomObject
                    {
                        Year = 2010,
                        Month = 7,
                        Value = 5
                    },
                new CustomObject
                    {
                        Year = 2010,
                        Month = 10,
                        Value = 3
                    }
            };

        var target = new List<CustomObject>
            {
                new CustomObject
                    {
                        Year = 2010,
                        Month = 7,
                        Value = 2
                    },
                new CustomObject
                    {
                        Year = 2010,
                        Month = 8,
                        Value = 1
                    },
                new CustomObject
                    {
                        Year = 2010,
                        Month = 10,
                        Value = 2
                    }
            };

        var merge = source.Merge(target, (x, y) => x.Year == y.Year && x.Month == y.Month);

        var toUpdate = merge.Matched((x, y) => x.Value != y.Value)
            .ToArray();

        var inSourceButNotInTarget = merge.NotMatchedBySource();

        var inTargetButNotInSource = merge.NotMatchedByTarget();

        Console.WriteLine("Objects to Update");
        foreach (var mergeMatched in toUpdate)
        {
            Console.WriteLine("{0} -{1} - {2} - {3}",
                mergeMatched.Source.Year,
                mergeMatched.Source.Month,
                mergeMatched.Source.Value,
                mergeMatched.Target.Value);
        }

        Console.WriteLine("In source but not in target");
        foreach (var customObject in inSourceButNotInTarget)
        {
            Console.WriteLine("{0} -{1} - {2} - 0",
                              customObject.Year,
                              customObject.Month,
                              customObject.Value);
        }

        Console.WriteLine("In target but not in source");
        foreach (var customObject in inTargetButNotInSource)
        {
            Console.WriteLine("{0} -{1} - 0 - {2}",
                              customObject.Year,
                              customObject.Month,
                              customObject.Value);
        }
    }
于 2013-07-23T23:35:18.057 回答