【问题标题】:Get from SourceB any element with an ID in SourceA从 Source 中获取任何具有 Source 中 ID 的元素
【发布时间】:2013-02-27 17:20:49
【问题描述】:

我一直在尝试为两个不同数据库中的两个模型构建一个看起来很奇怪的连接方法,您可以查询第一个,然后返回一个小的 id 列表以在另一个数据库中搜索。一切正常,除了一两件事,我无法使用 lambda 函数执行 Id 列表子查询,我有链接通用的 Id 选择器函数,但在 where 子句中它现在可以工作,因为我不知道谁链接源类型对象传递给 Id 的函数,因此 .Where(TSource => idlist.Contains(Idselector) 示例代码低于由于 List.Conatins 代码而中断的位置。如果有人可以提供帮助,我将不胜感激

public static Foo JoinTwoModels<T1,T2>(
           DbSet Dbs1,
           DbSet Dbs2,
           Expression<Func<T1, object>> Id1,
           Expression<Func<T1, dynamic>> Selector1,
           Expression<Func<T1, bool>> Search1,
           Expression<Func<T2, object>> Id2,
           Expression<Func<T2, dynamic>> Selector2)
        {
            var Output1 = Queryable.OfType<T1>(Dbs1);

            var Output2 = Queryable.OfType<T2>(Dbs2);

            List<dynamic> Result1 = Output1.Where(Search1).Select(Selector1).ToList();

            List<object> idList = new List<object>();

            PropertyInfo p1 = Result1[0].GetType().GetProperty("Id");

            foreach (var o1 in Result1)
            {
                idList.Add(p1.GetValue(o1));
            }

            //Query result entries into db
            List<T2> Result2 = Output2.Where(idlist.contains(Id2)).ToList();

【问题讨论】:

    标签: c# asp.net linq entity-framework lambda


    【解决方案1】:

    这样的事情怎么样:

    public class Foo
    {
        public int Context;
        public string Data;
    }
    
    public class Bar
    {
        public int Context;
        public string Data;
    }
    
    public static IEnumerable<TOutput> JoinTwoModels<T1, T2, TIdent, TOutput>(
        IEnumerable<T1> sourceA,
        IEnumerable<T2> sourceB,
        Func<T1, TIdent> idSelectorA,
        Func<T2, TIdent> idSelectorB,
        Func<T1, TOutput> selectorA,
        Func<T2, TOutput> selectorB)
    {
    
        var queryA = sourceA
                .Select(x => new {Value = selectorA(x),Id = idSelectorA(x)});
    
        var queryB = sourceB
                .Select(y => new {Value = selectorB(y),Id = idSelectorB(y)})
                .Where(y => queryA.Select(x => x.Id).Contains(y.Id))
                .Select(y => y.Value);
    
        return queryA.Select(x => x.Value).Concat(queryB);
    }
    
    private static void Main(string[] args)
    {
        var sourceA = new List<Foo>() {new Foo() {Context = 2, Data = "I'm a Foo"}};
        var sourceB = new List<Bar>() {new Bar() {Context = 2, Data = "I'm a Bar"}};
    
        var Output1 = sourceA.AsQueryable();
        var Output2 = sourceB.AsQueryable();
    
        var results = JoinTwoModels(
            Output1,
            Output2,
            (Func<Foo, int>) (x => x.Context),
            (Func<Bar, int>) (x => x.Context),
            (Func<Foo, string>) (x => x.Data),
            (Func<Bar, string>) (x => x.Data));
    
        foreach (var item in results)
            Console.WriteLine(item);
    }
    

    你想要的不是很清楚;所以在上面,我从 Source-A(Foo 类型)和 Source-B(Bar 类型)中选择了共享一个公共上下文(id)的所有项目,并以转换后的公共类型返回它们。

    如果您只想要 b 中的值,则可以将其简化为:

    var queryA = sourceA.Select(idSelectorA);
    
    var queryB = sourceB
            .Select(y => new {Value = selectorB(y),Id = idSelectorB(y)})
            .Where(y => queryA.Select(x => x).Contains(y.Id))
            .Select(y => y.Value);
    
    return queryB;
    

    【讨论】:

    • 感谢您的回复和帮助大卫,您说得对,我想在 Id 上将两个结果合并在一起,但我希望每次都能灵活地选择多个/不同的字段,因此动态函数返回,我只是中级,所以不确定,但你的固定值/id属性是固定的,还是返回的数字字段是动态的?这似乎也是 linq-to-object IEnumberable 查询,这对于 IQueryable 到 DB 是否同样有效?再次感谢
    • 首先,IEnumerable 不会运行,直到您遍历结果;所以我认为在 IQueryable 上运行 IEnumerables 是安全的(尽管我从未尝试过)。至于动态; dynamic 将问题从编译时转移到运行时。我会尽量避免它并使用强类型... Foo、T1、T2 和 TOutput 可以是任何东西。但我想您的数据库将有两列,ID 和 VALUE,并且 VALUE 的类型不会因行而异。
    • 也不要混淆两个问题;去获取匹配 ID 的值;它将作为 IEnumerable 返回...将其转换为 Query 并在其上运行您的数据字段选择。即您可以将 T1 和 T2 作为 IQueryable。等等……
    • 谢谢,我有多个值/字段我想从每个源返回(并动态选择),但可以理解在运行时使用动态和调试不是上帝的做法。在返回整个对象数据集的查询之上的几个字段上运行我的数据字段选择对性能来说还不错吗?抱歉问了这么多问题,您的帮助最大
    • 是的,这个位 quearyA.Select(x => x).Contains(y.Id) 每次都会在 databaseA 上运行查询。如果你把它拉出来解决它,它只会运行一次。即 .ToList()。但是现在,您正在解决其他问题中的查询。所以,分手吧。没有一种方法可以做两件事。
    猜你喜欢
    • 1970-01-01
    • 2019-11-23
    • 2019-01-25
    • 2021-03-03
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    • 2014-02-27
    • 2012-10-07
    相关资源
    最近更新 更多