将SQL查询转换为LINQ方法语法



有人能帮我把下面的SQL查询翻译成LINQ格式吗→方法语法?

select Employees.Id,Positions.Name from Employees 
left join Contracts on Employees.Contract_id=Contracts.Id
left join Positions on Contracts.Position_Id=Positions.Id

我认为,当人们从SQL开始,从LINQ和EF开始时,他们可能没有意识到EF在幕后会为他们做多少。他们从SQL的角度知道他们所知道的;我需要一个连接b连接c,所以我需要在c#中使用linq连接"-也许他们找到了查询语法,也许他们写了一些有效的东西,然后想知道如何将其转换为方法语法(这并不总是一个好主意;linq中的一些东西比查询语法整洁得多(

不过,没有必要如此强烈地参与EF。如果你已经设置了客户端实体,所以它们之间有导航属性:

//employee has a contract has a position
//positions has contracts has employees
public class Employee{
public int Id{get;set;}
public Contract Contract {get;set;}
}
public class Contract{
public int Id{get;set;}
public Position Position {get;set;}
public ICollection<Employee> Employees {get;set;}
}
public class Position{
public int Id{get;set;}
public string Name {get;set;}
public ICollection<Contract> Contracts {get;set;}
}

然后EF知道实体和表是如何关联的,所以只需简单地说:

context.Employees.Select(r => new { e.Id, e.Contract.Position.Name } );

EF将执行获取所请求的数据所需的所有联接。您不需要像SQL那样对它进行每次连接。这是一个";对象/关系映射器"-它的工作是了解这里的一组对象,它看起来像一个双向链接的树,在那里你可以使用.成员访问操作符在分支上来回移动。。以及那里的一组表,用于维护树中的数据。它将观察您浏览树并形成SQL,为结果提供数据

它不是完美的,也不是通用的,但它很好,知道一些巧妙的技巧(例如,如果你说contracts.Select(c => new { c, c.Employees.OrderByDescending(e => e.HireDate).First() }),它会把它写成ROW_NUMBER() OVER(PARTITION BY employeeid ORDER BY hiredate DESC) ..WHERE rn = 1(,所以对于它能力范围内的最常见的东西,你可以留在C#中,让它继续翻译。你会很快发现你是否达到了它的极限(它会为任何无法翻译的东西抛出一个例外(


脚注:

我一直在想,既然在表之间设置了键等,为什么永远不能只写一个像这样的SQL

SELECT e.Id, e.Contracts.Positions.Name
FROM e
WHERE ...

并沿着一段关系旅行;朝向1端";方向自动。为什么它总是那么手动?为什么很少使用像NATURAL JOIN这样几乎无用的鲤鱼,并且在具有PK:FK关系的两个列上没有可以加入的东西?但是,当你读到DBA所说的话时,你会更清楚地看到,程序员和DBA对事物的看法略有不同,也更容易理解为什么他们(和数据库开发人员(可能希望保持他们非常特定的设置方式,以及为什么对它们进行抽象以提供自动连接是程序员在不同级别上要做的事情

var data =
from e in db.Employees
join c in db.Contracts on e.Contract_id equals c.Contract_id
into ct from c in ct.DefaultIfEmpty()
join p in db.Positions on c.Position_Id equals p.Position_Id
into pt from p in pt.DefaultIfEmpty()
select new { Id = e.Id, Name = p.Name };

注意:DefaultIfEmpty与left join here 的作用相同

最新更新