只有在不为空的情况下如何连接表?

How to join tables only if not empty?

我有以下 LINQ 查询:

var LINQFilter = (from Cash in _DataTable_Cash.AsEnumerable()
                  join CashOpeningsAssignments in _DataTable_CashOpeningsAssignments.AsEnumerable().Where(a => (a.Field<Int32>("cashopeningassignmentstatus_id") == 1 || a.Field<Int32>("cashopeningassignmentstatus_id") == 2))
                       on Cash.Field<Int32>("cash_id") equals CashOpeningsAssignments.Field<Int32>("cash_id") into into_cashopeningsassignments
                  from CashOpeningsAssignments in into_cashopeningsassignments.DefaultIfEmpty()
                  join Users in _DataTable_Users.AsEnumerable()
                       on CashOpeningsAssignments.Field<Int32>("user_id") equals Users.Field<Int32>("user_id") into into_users
                  from Users in into_users.DefaultIfEmpty() 
                  select new
                  {
                      cash_id = Cash.Field<Int32>("cash_id"),
                      cellar_name = Cellars.Field<String>("cellar_name"),
                      cash_name = Cash.Field<String>("cash_name"),
                      cashstatus_name = CashStatus.Field<String>("cashstatus_name"),
                      user_name = (Users == null ? "[No Data]" : Users.Field<String>("user_firstname") + (Char)32 + Users.Field<String>("user_lastname")),
                      cashtransaction_amount = (Cash.Field<Int32>("cashstatus_id") == 2 ? 0.00 : 150.00)
                  });

我在显示结果时遇到问题,因为此字段 returns 为空:CashOpeningsAssignments.Field<Int32>("user_id")CashOpeningsAssignments 为空时。

我尝试将 .DefaultIfEmpty() 移动到用户中,但仍然无法正常工作,知道我该如何解决这个问题吗?

回答

使用 DefaultIfEmpty 的重载创建一个空项目。

例如

into_cashopeningsassignments
    .DefaultIfEmpty(new CashOpeningsAssignments()) 

运行代码

该代码反映了您正在尝试做的事情,尽管我对其进行了一些改动。例如,我使用 List<T> 而不是 DataTable,因为我不知道如何在 DotNetFiddle 中使用 Field<T>(string name)

现场直播:https://dotnetfiddle.net/YaAc6D

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {   
        var query = 
            from Cash 
            in _DataTable_Cash.AsEnumerable()
            join CashOpeningsAssignments 
            in _DataTable_CashOpeningsAssignments.AsEnumerable()
                .Where(a => 
                    (a.cashopeningassignmentstatus_id == 1 || 
                     a.cashopeningassignmentstatus_id == 2))
            on Cash.cash_id 
            equals CashOpeningsAssignments.cash_id 
            into into_cashopeningsassignments

            from CashOpeningsAssignments 
            in into_cashopeningsassignments.DefaultIfEmpty(new CashOpeningsAssignments()) 
            join Users 
            in _DataTable_Users.AsEnumerable()
            on CashOpeningsAssignments.user_id 
            equals Users.user_id
            into into_users

            from Users 
            in into_users.DefaultIfEmpty() 
            select new
            {
                cash_id = Cash.cash_id,
                // cellar_name = Cellars.cellar_name,
                cash_name = Cash.cash_name,
                // cashstatus_name = CashStatus.cashstatus_name,
                user_name = (Users == null ? "[No Data]" : Users.user_firstname + (Char)32 + Users.user_lastname),
                cashtransaction_amount = (Cash.cashstatus_id == 2 ? 0.00 : 150.00)
            };

        foreach(var result in query)
        {
            Console.WriteLine(result);
        }
    }

    public static List<Cash> _DataTable_Cash = 
        new List<Cash> { new Cash() };

    public static List<Cellars> _DataTable_Cellars = 
        new List<Cellars> { new Cellars() };

    public static List<CashStatus> _DataTable_CashStatus = 
        new List<CashStatus> { new CashStatus() };

    public static List<CashOpeningsAssignments> _DataTable_CashOpeningsAssignments = 
        new List<CashOpeningsAssignments> { };

    public static List<Users> _DataTable_Users =
        new List<Users>() { new Users() };
}

public class Cash
{
    public int cash_id { get; set; }
    public string cash_name { get; set; }
    public int cellar_id { get; set; }
    public int cashstatus_id { get; set; }
}

public class Cellars
{
    public string cellar_name { get; set; }
    public int cellar_id { get; set; }
}

public class CashStatus
{
    public int cashstatus_id { get; set; }
    public string cashstatus_name { get; set; }
}

public class CashOpeningsAssignments
{
    public int user_id { get; set; }
    public int cash_id { get; set; }
    public int cashopeningassignmentstatus_id { get; set; }
}

public class Users
{
    public string user_firstname { get; set; }
    public string user_lastname { get; set; }
    public int user_id { get; set; }
}

另请参阅

https://msdn.microsoft.com/en-us/library/vstudio/bb355419%28v=vs.100%29.aspx