LINQ To Objects - 加入空列表

时间:2017-07-19 21:48:13

标签: c# linq linq-to-objects

我有三个单独的列表,这些列表是从不同的数据源填充的,现在我想在LINQ语句中将它们加入到我的最终结果中。但是,完全有可能其中一个列表可能是空的。看来如果列表为空,我不能只编写一个LINQ语句来加入其中任何一个。

我写了以下测试。我得到的错误是“NullReferenceException:对象引用未设置为对象的实例。”

// these colloections emulate the table structures and data
List<Agent> agents = new List<Agent>();
agents.Add(new Agent { AgentId = 1, ClientId = 11 });
agents.Add(new Agent { AgentId = 1, ClientId = 12 });
agents.Add(new Agent { AgentId = 1, ClientId = 13 });
agents.Add(new Agent { AgentId = 1, ClientId = 14 });
agents.Add(new Agent { AgentId = 2, ClientId = 21 });
agents.Add(new Agent { AgentId = 2, ClientId = 22 });
agents.Add(new Agent { AgentId = 3, ClientId = 31 });

List<Client> clients = new List<Client>();
clients.Add(new Client { ClientId = 11, ClientName = "A Client 11", Status = "A" });
clients.Add(new Client { ClientId = 12, ClientName = "A Client 12", Status = "A" });
clients.Add(new Client { ClientId = 13, ClientName = "A Client 13", Status = "A" });
clients.Add(new Client { ClientId = 14, ClientName = "A Client 14", Status = "A" });
clients.Add(new Client { ClientId = 21, ClientName = "A Client 21", Status = "A" });
clients.Add(new Client { ClientId = 22, ClientName = "A Client 22", Status = "A" });
clients.Add(new Client { ClientId = 31, ClientName = "A Client 31", Status = "A" });

// Upon initilization, there are no records here.  Eventually, this "table" will be populated, 
// but only after the user has used the app for a while. If I populate this list, it works assuming
// the agent ID I'm looking for is in the collection.  But if it's not the join fails
List<ClientAdminFee> adminFees = new List<ClientAdminFee>();
//  adminFees.Add(new ClientAdminFee { AgentId = 1, ClientId = 11, AdminFee = 0.05m, EffectiveFrom = DateTime.Parse("2017-01-01") });
//  adminFees.Add(new ClientAdminFee { AgentId = 1, ClientId = 12, AdminFee = 0.05m, EffectiveFrom = DateTime.Parse("2017-01-01") });
//  adminFees.Add(new ClientAdminFee { AgentId = 1, ClientId = 13, AdminFee = 0.05m, EffectiveFrom = DateTime.Parse("2017-01-01") });
//  adminFees.Add(new ClientAdminFee { AgentId = 1, ClientId = 14, AdminFee = 0.05m, EffectiveFrom = DateTime.Parse("2017-01-01") });

var thisAgent = 1;
var theseAgents = agents.Where(x => x.AgentId == thisAgent).ToList();
var theseClients = clients.ToList();
var theseAdminFees = adminFees.Where(x => x.AgentId == thisAgent).ToList();

var final = (from ar in theseAgents
             join c in theseClients on ar.ClientId equals c.ClientId
             join caf in theseAdminFees on new { ar.AgentId, c.ClientId } equals new { caf.AgentId, caf.ClientId } into d
             from caf in d.DefaultIfEmpty()
             select new ClientWithAdminFee
             {
                 AgentId = Convert.ToInt32(ar.AgentId),
                 ClientId = Convert.ToInt32(c.ClientId),
                 ClientName = c.ClientName,
                 Status = c.Status,
                 AdminFee = caf.AdminFee ?? 0.00m,
                 EffectiveDate = caf.EffectiveFrom ?? DateTime.Now
             }).ToList();

final.Dump();

正如我所说的,如果我取消注释adminFees条目,并搜索AgentId 1,它就可以了。但是,如果我搜索不在该集合中的代理,我根本无法进行连接。那么我怎么能写这个如果它有条目,如果没有条目,它可以正常工作。

1 个答案:

答案 0 :(得分:1)

试试这个

var final = (from ar in theseAgents
                         join c in theseClients on ar.ClientId equals c.ClientId
                         join caf in theseAdminFees on new { ar.AgentId, c.ClientId } equals new { caf.AgentId, caf.ClientId } into d
                         from caf in d.DefaultIfEmpty()
                         select new ClientWithAdminFee
                         {
                             AgentId = Convert.ToInt32(ar.AgentId),
                             ClientId = Convert.ToInt32(c.ClientId),
                             ClientName = c.ClientName,
                             Status = c.Status,
                             AdminFee = caf != null ? (caf.AdminFee) : 0,
                             EffectiveDate = caf != null ? (caf.EffectiveFrom == null ? DateTime.Now : caf.EffectiveFrom) : DateTime.Now,
                         }).ToList();