参考文档:​​https://docs.microsoft.com/en-us/dotnet/csharp/linq/perform-inner-joins​

1:内连接join

var query = from emp in t.Employees
join ed in t.EmployeeDetails on emp.Id equals ed.EDId
select new { emp.Id, emp.Name, final?.Address };

2:左连接

var query = from emp in t.Employees
join ed in t.EmployeeDetails on emp.Id equals ed.EDId into tmp
from final in tmp.DefaultIfEmpty()
select new { emp.Id, emp.Name, final?.Address };

使用 join in on  t.id equals x.id into temp from z in  temp.DefaultIfEmpty()

3:右连接

var query = from ed in t.EmployeeDetails
join emp in t.Employees on emp.Id equals ed.EDId
select new { emp.Id, emp.Name, final?.Address };


备注:?. 表示对象不为空执行后面

关于C#中?的使用含意:

1:三元表达式(逻辑判断)

string name=class==1?"班级1"“其它”

2:连接对象(空合并运算符)

string name = null;

string name2 = "jition";

string c = name  ?? name2 ; 

//如果name 为null,就返回name2 (??左边为null则返回??右边,??左边不为null则返回??左边);

3:访问修饰符(允许为null的数据类型)

一般基本类型是不允许null 

如:

private int ? age{get;set}

      private bool ? status{get;set};

      private DateTime? CreateTime{get;set};

4: NULL检查运算符(?.)

对象允许为null,不会抛出空指针异常

   int? firstX = null;    
if (points != null)
{
var first = points.FirstOrDefault();
if (first != null)
firstX = first.X;
}

在C# 6.0中,引入了一个 ?. 的运算符,前面的代码可以改成如下形式:

    int? firstX = points?.FirstOrDefault()?.X;

  基本用法:如果对象为NULL,则不进行后面的获取成员的运算,直接返回NULL