在这个例子中,我有一个下面的表,其中一列为"受限访问"。我有另一张表,里面有访问信息。使用linq连接下面的表的最好方法是什么?
我们有主表,我们将其命名为reports
的报告id | report | isRestricted | 1 | 0 | 2
---|---|---|
b | 1 | |
3 | c | 1 |
假设你已经把你的导航属性都连接好了(一个Report有一个ICollection of Access)等等,你可以问:
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))
这将变成一个sql,它使用一个协调的EXISTS来检查公司是否存在于该报告的access表中
在任何一种情况下,我认为DB可能会以类似的方式计划和执行查询,但如果你知道哪个更执行,你将不得不比赛你的马!
如果我们从普通对象开始,我们可以:
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上,我认为如果你能在从数据库读取和操纵记录后提供视图/数据结构/上下文,这将有助于其他人回答你的问题。