【问题标题】:How to query by composite keys using ORM + LINQ? [duplicate]如何使用 ORM + LINQ 通过复合键查询? [复制]
【发布时间】:2014-01-10 02:19:26
【问题描述】:

我有一个内存对象数组,代表我想查询的复合键,例如:

public class Key
{
    public string Part1 {get;set;}
    public string Part2 {get;set;}
}

现在假设我有一个IQueryable<Table1>,我想返回上面Keys 的所有记录。 Table1 没有代理键,它有一个由 2 列组成的复合键。我也想避免每行检索。

我该怎么做?我尝试了标准连接,但由于明显的原因,当内存中的对象被混合时,我的 ORM 会感到困惑。

【问题讨论】:

    标签: c# linq entity-framework orm llblgen


    【解决方案1】:

    在类似的情况下,我发现最好的解决方案是在数据库中进行第一次选择,然后在内存中进行精确匹配:

    var parts1 = Keys.Select(k => k.Part1).ToArray();
    var parts2 = Keys.Select(k => k.Part2).ToArray();
    
    var dbSelection = context.TableRecords.Where(r => parts1.Contains(r.Part1)
                                                   && parts2.Contains(r.Part2);
    
    var finalSelection = from record in dbSelection
                                        .AsEnumerable() // to memory
                         join key in Keys on new { record.Part1, record.Part2 }
                                             equals
                                             new { key.Part1, key.Part2 }
                         select record;
    

    如果你有钥匙

    1,2
    2,1
    

    那么dbSelection 也将包含{1,1} 和{2,2}(但不是绝大多数其他记录)。这些被第二个查询过滤掉了。

    优点是数据库查询可以利用索引,如果您使用计算键(如连接键值),这是不可能的。

    缺点是你必须确保parts1parts2不能过度增长,否则SQLIN语句会因为元素太多而变得非常低效甚至崩溃(我们说的是成千上万Sql Server 的项目)。但对于任何使用 Contains 的解决方案都是如此。

    【讨论】:

    • 很好的尝试我猜答案是真的,做不到。虽然预过滤有帮助,但正如您所说,它对于更大的问题是不可扩展的。
    • 不,ContainsIN 声明缺乏可扩展性是真正的 PIA。我也有解决方案,我 UNION 查询其中 IN 是分块完成的。精致+丑陋。
    【解决方案2】:

    一种解决方法可以使用串联

    类似的东西。

    var keys = new List<Key> {
        {new Key {Part1="12", Part2="3"},
        {new Key {Part1="1", Part2="23"}
        };
    
    var concatenatedKeys = keys.Select(m => m.Part1 + "~" + m.Part2).ToList();
    
    var queryable = repository.MyEntity.Where(x => concatenatedKeys.Contains(x.CompositeKey1 + "~" + x.CompositeKey2);
    

    分隔符(在本例中为~)是任意的,表示您的字符串中找不到的字符。

    这是为了避免“错误”匹配(例如,12 和 3 与 1 和 23)

    【讨论】:

    • 这可能有很大的缺点,因为查询不会在服务器端进行评估。
    • @Alwyn 一点也不。这就是这个解决方案的“好”点。
    • 听起来不错,但是可以索引吗?
    • 如果您在表中使用连接复合键添加列,则可以轻松添加索引。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-13
    • 1970-01-01
    相关资源
    最近更新 更多