【问题标题】:What is the most efficient Linq statement to query these tables? [closed]查询这些表最有效的 Linq 语句是什么? [关闭]
【发布时间】:2021-12-08 19:54:25
【问题描述】:

在此示例中,我有一个下表,其中有一列用于“受限访问”。我有另一个包含访问信息的表。使用 linq 加入下表的最佳方法是什么?

我有一个我们称之为报告的主表

报告

id report isRestricted
1 a 0
2 b 1
3 c 1

我还有第二个表,我们称之为 Access

访问

id company report
1 google b
2 alphabet c

在代码中,我想创建一个具有以下条件的列表:

  • 如果 isRestricted 为 0,它将显示给任何试图访问的公司
  • 如果 isRestricted 为 1,则仅当当前公司的访问表中有条目时才显示该报告

所以

var currentCompany = “google”;

我希望返回一个带有报告“a”和“b”的列表。

我将如何使用 linq 完成此任务?

【问题讨论】:

  • linq 标签建议您在 LINQ 中执行此操作。所以好的开始是找到一个支持 LINQ 的 O/R 映射器。它也有助于展示你自己的第一次努力。他们比你想象的更清楚。
  • 定义“高效”。如果您的意思是高性能,那么您需要考虑索引。您可能需要索引 REPORT (report) INCLUDE (id, isRestricted)ACCESS (company, report)

标签: c# sql linq


【解决方案1】:

假设您的导航属性全部正确连接(报告具有 ICollection 访问权限)等,您可以问:

var q = context.Reports.Where(r => r.IsRestricted == 0 || r.Accesses.Any(a => a.Company == currentCompany))

EF 将进行必要的连接等。如果您使用的是 EF5 并想查看它编写的 SQL,请在运行 Where 后暂停调试器并查看 Q 变量的 DebugView 属性。我认为这个变成了一个只针对谷歌的子查询的左连接,要求左连接不为空(但很难记住它们是如何翻译的)

如果您尚未在模型中的表之间建立任何关系,它可能需要看起来更像:

var q = context.Reports.Where(r => r.IsRestricted == 0 || context.Accesses.Any(a => r.Report == a.Report && a.Company == currentCompany))

这将变成一个使用协调 EXISTS 来检查公司是否存在于该报告的 Accesses 表中的 sql

在任何一种情况下,我认为数据库可能会以类似的方式计划和执行查询,但如果您想知道哪个性能更好,您将不得不与您的马赛跑!

【讨论】:

    【解决方案2】:

    如果我们从普通对象开始,我们可以这样做:

    using System;
    using System.Linq;
                        
    public class Program
    {
        public static void Main()
        {
            var reports = new []
            {
                new { Id = 1, Report = "a", IsRestricted = 0 },
                new { Id = 2, Report = "b", IsRestricted = 1 },
                new { Id = 3, Report = "c", IsRestricted = 1 }
            };
            
            var accesses = new [] 
            {
                new { Id = 1, Company = "google", Report = "b" },
                new { Id = 2, Company = "alphabet", Report = "c" }
            };
            
            var currentCompany = "google";
            
            var list = reports
                .Where(r => r.IsRestricted == 0)
                .Select(r => r.Report)
                .Concat(accesses
                        .Where(a => a.Company == currentCompany)
                        .Select(a => a.Report)
                )
                .Distinct()
                .ToList();
            
            System.Console.WriteLine(list.Aggregate((a, b) => a + "," + b));
        }
    }
    

    这将打印a,b

    由于您的问题集中在 LINQ 上,我认为如果您可以在从数据库读取和操作记录后提供视图/数据结构/上下文,这将有助于其他人回答您的问题。

    【讨论】:

      猜你喜欢
      • 2017-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-22
      • 2011-02-19
      相关资源
      最近更新 更多