Sử dụng biểu thức lambda để thực hiện Left Join và Inner Join

Sử dụng biểu thức lambda để thực hiện Left Join và Inner Join

Left Join

Biểu thức lambda chỉ phù hợp cho việc kết nối hai bảng, nếu nhiều hơn thì sẽ phức tạp.

Phương thức DefaultIfEmpty() là chìa khóa ở đây.

var ketQua = CustomerFollowup
    .Where(a => !a.IsDelete && a.CustomerID == request.CustomerID)
    .GroupJoin(Org, a => a.CreateOrgId, b => b.Id, (a, b) => new { Followup = a, Org = b })
    .SelectMany(t => t.Org.DefaultIfEmpty(), (a, b) => new
    {
        TenDonVi = b.Name,
        NoiDung = a.Followup.Contents
    }).ToList();

SQL được tạo ra:

SELECT [o].[Name] AS [TenDonVi], [c].[Contents]
FROM [CustomerFollowup] AS [c]
LEFT JOIN [Org] AS [o] ON [c].[CreateOrgId] = [o].[Id]
WHERE ([c].[IsDelete] = 0) AND ([c].[CustomerID] = @__request_CustomerID_0)

Đối với việc kết nối nhiều bảng, có thể sử dụng linq, nhưng thực sự không thích cách này vì nó không trực quan.

var ketQua1 = from p in CustomerFollowup
              from donVi in Org.Where(c => c.Id == p.CreateOrgId).DefaultIfEmpty()
              from nguoiDung in User.Where(c => c.Id == p.CreateUserId).DefaultIfEmpty()
              where !p.IsDelete && p.CustomerID == request.CustomerID
              select new
              {
                  NoiDung = p.Contents,
                  TenDonVi = donVi.Name,
                  TenNguoiDung = nguoiDung.Name
              };
var ketQua2 = from p in CustomerFollowup.Where(a => !a.IsDelete && a.CustomerID == request.CustomerID)
              from donVi in Org.Where(c => c.Id == p.CreateOrgId).DefaultIfEmpty()
              from nguoiDung in User.Where(c => c.Id == p.CreateUserId).DefaultIfEmpty()
              select new
              {
                  NoiDung = p.Contents,
                  TenDonVi = donVi.Name,
                  TenNguoiDung = nguoiDung.Name
              };

Cần lưu ý rằng, không thể chuyển đổi trực tiếp sang danh sách, phải tách riêng:

var danhSach1 = ketQua1.ToList();
var danhSach2 = ketQua2.ToList();

Cả hai cách viết này đều tạo ra cùng một kết quả SQL:

SELECT [c].[Contents], [o].[Name] AS [TenDonVi], [u].[Name] AS [TenNguoiDung]
FROM [CustomerFollowup] AS [c]
LEFT JOIN [Org] AS [o] ON [c].[CreateOrgId] = [o].[Id]
LEFT JOIN [User] AS [u] ON [c].[CreateUserId] = [u].[Id]
WHERE ([c].[IsDelete] = 0) AND ([c].[CustomerID] = @__request_CustomerID_0)

Inner Join

var ketQua = UnitWork.Find<CustomerFollowup>(a => !a.IsDelete && a.CustomerID == request.CustomerID)
    .Join(UnitWork.Find<Org>(null), a => a.CreateOrgId, b => b.Id, (a, b) => new { a, TenDonVi = b.Name })
    .Join(UnitWork.Find<User>(null), a => a.a.CreateUserId, b => b.Id, (a, b) => new { a, TenNguoiDung = b.Name })
    .Join(UnitWork.Find<SysParamInfo>(null), a => a.a.a.Type, b => b.ParamValue, (a, b) => new { a, TenLoai = b.ParamName })
    .Join(UnitWork.Find<CustomerPhone>(null), a => a.a.a.a.ObjectUser, b => b.Id, (a, b) => new { a, TenDienThoai = b.Name })
    .Select(a => new
    {
        Loai = a.a.TenLoai,
        NoiDung = a.a.a.a.a.Contents,
        ThoiGianTao = a.a.a.a.a.CreateTime,
        NguoiDung = a.TenDienThoai,
        TenDonVi = a.a.a.a.TenDonVi,
        Khac = a.a.a.a.a.Other,
        TenNguoiDung = a.a.TenNguoiDung
    });

Dùng cho truy vấn phân trang:

result.data = ketQua.OrderByDescending(u => u.ThoiGianTao)
                    .Skip((request.page - 1) * request.limit)
                    .Take(request.limit);
result.count = ketQua.Count();

Kết quả SQL:

SELECT COUNT(*) FROM [CustomerFollowup] AS [c]
INNER JOIN [Org] AS [o] ON [c].[CreateOrgId] = [o].[Id]
INNER JOIN [User] AS [u] ON [c].[CreateUserId] = [u].[Id]
INNER JOIN [SysParamInfo] AS [s] ON [c].[Type] = [s].[ParamValue]
WHERE ([c].[IsDelete] = 0) AND ([c].[CustomerID] = @CustomerID)

SELECT [s].[ParamName] AS [Loai], [c].[Contents], [c].[CreateTime], [c].[ObjectUser], [o].[Name] AS [TenDonVi], [c].[Other], [u].[Name] AS [TenNguoiDung]
FROM [CustomerFollowup] AS [c]
INNER JOIN [Org] AS [o] ON [c].[CreateOrgId] = [o].[Id]
INNER JOIN [User] AS [u] ON [c].[CreateUserId] = [u].[Id]
INNER JOIN [SysParamInfo] AS [s] ON [c].[Type] = [s].[ParamValue]
WHERE ([c].[IsDelete] = 0) AND ([c].[CustomerID] = @CustomerID)
ORDER BY [c].[CreateTime] DESC OFFSET @__p_1 ROWS FETCH NEXT @__p_2 ROWS ONLY

Thẻ: .NET linq C# sql Entity Framework

Đăng vào ngày 30 tháng 5 lúc 18:15