[英]How do I use a left-join and non-left-join on more than 2 tables using linq
I am trying to join 3 tables into a specific model using linq but I am getting incorrect results.我正在尝试使用 linq 将 3 个表加入特定的 model 但我得到的结果不正确。
var filteredEmployees = _employeesRepository.GetAll(); //TODO: Filter
var filteredSchedules = _schedulesRepository.GetAll(); //TODO: Filter
var filteredPunches = _punchesRepository.GetAll(); //TODO: Filter
var innerGroupJoinQuery =
from allEmployees in filteredEmployees
join allSchedule in filteredSchedules on allEmployees.FileNumber equals allSchedule.FileNumber
join allPunches in filteredPunches on allSchedule.Id equals allPunches.ScheduleId
select new {Employee = allEmployees, Schedule = allSchedule, Punches = allPunches}; <-- this part doesnt seem correct to me
var innerGroupJoinQueryList = innerGroupJoinQuery.ToList();
var inner2 = innerGroupJoinQueryList
.GroupBy(g => g.Employee)
.Select(s => new JanusWeeklyOverviewDto()
{
Employee = ObjectMapper.Map<EmployeesDto>(s.Key),
ScheduleAndPunches = s.Select(s2 => new ScheduleAndPunchesDto()
{
Schedule = ObjectMapper.Map<SchedulesDto>(s2.Schedule),
Punches = s.Where(w => w.Schedule.Id == w.Punches.ScheduleId).Select(s3 => ObjectMapper.Map<PunchesDto>(s3.Punches)),
})
})
.ToList();
Problem 1 :问题1 :
In the ScheduleAndPunches
model, there is exactly 7 Schedule
record for every Employee
between a given week range (Sunday 2/14 to Saturday 2/20) but it currently only returns records that have a Punch
entry.在ScheduleAndPunches
model 中,在给定的一周范围(2/14 星期日到 2/20 星期六)之间,每个Employee
恰好有 7 Schedule
记录,但它目前只返回具有Punch
条目的记录。
Q1 : How would I change my code so that it does a left-join and pulls all 7 Schedule
records and the Punch
record associated (if any). Q1 :我将如何更改我的代码,以便它进行左连接并提取所有 7 Schedule
记录和关联的Punch
记录(如果有)。
Problem 2 :问题2 :
In the ScheduleAndPunches
model, punches returns all Punches
record, ignoring the Schedule.Id
its associated with.在ScheduleAndPunches
model 中,punches 返回所有Punches
记录,忽略与其关联的Schedule.Id
。
Q2 : How would I change my code so that it pulls all Punches
records based on the Schedule.Id
. Q2 :我将如何更改我的代码,以便它根据Schedule.Id
提取所有Punches
记录。
SELECT TOP (100) PERCENT
Janus.Employees.FileNumber,
Janus.Employees.HomeDepartment,
Janus.Employees.LastName,
Janus.Employees.FirstName,
Janus.Schedules.Id AS ScheduleId,
Janus.Schedules.ScheduleDate,
Janus.Schedules.EndDate,
Janus.Schedules.StartTime,
Janus.Schedules.EndTime,
Janus.Schedules.ForcedLabor,
Janus.Punches.Id AS PunchId,
Janus.Punches.TimeStamp,
Janus.Punches.OriginalTimeStamp,
Janus.Punches.CurrentState,
Janus.Punches.WasOverridden,
Janus.Punches.OverrideId,
Janus.Punches.EnteredBy,
Janus.Punches.Comments
FROM
Janus.Employees
INNER JOIN Janus.Schedules
ON Janus.Employees.FileNumber = Janus.Schedules.FileNumber
LEFT OUTER JOIN Janus.Punches
ON Janus.Schedules.Id = Janus.Punches.ScheduleId -- AND Janus.Schedule.FileNumber = Janus.Punches.FileNumber
WHERE
(Janus.Employees.FileNumber = '8095')
AND (Janus.Schedules.ScheduleDate BETWEEN '20210214' AND '20210220')
ORDER BY
Janus.Employees.FileNumber,
Janus.Schedules.ScheduleDate,
Janus.Punches.TimeStamp DESC
public class JanusWeeklyOverviewDto
{
public EmployeesDto Employee { get; set; }
public IEnumerable<ScheduleAndPunchesDto> ScheduleAndPunches { get; set; }
}
public class ScheduleAndPunchesDto
{
public SchedulesDto Schedule { get; set; }
public IEnumerable<PunchesDto> Punches { get; set; }
}
public class EmployeesDto : EntityDto
{
public string FileNumber { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string BadgeNumber { get; set; }
public DateTime? HiredDate { get; set; }
public DateTime? DateOfBirth { get; set; }
public decimal? Rate { get; set; }
public string RateType { get; set; }
public string HomeDepartment { get; set; }
public string Status { get; set; }
public int? LunchRule { get; set; }
public DateTime? EffectiveDate { get; set; }
public string Comments { get; set; }
public string CurrentState { get; set; }
public string OvertimeState { get; set; }
public DateTime? TerminationDate { get; set; }
public string Role { get; set; }
public string Profile { get; set; }
public byte[] Photo { get; set; }
public int? PhotoFileId { get; set; }
}
public class SchedulesDto : EntityDto
{
public string FileNumber { get; set; }
public DateTime? ScheduleDate { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public DateTime? EndDate { get; set; }
public string ForcedLabor { get; set; }
}
public class PunchesDto : EntityDto
{
public string FileNumber { get; set; }
public DateTime TimeStamp { get; set; }
public DateTime OriginalTimeStamp { get; set; }
public string CurrentState { get; set; }
public string WasOverridden { get; set; }
public string OverrideId { get; set; }
public string EnteredBy { get; set; }
public string Comments { get; set; }
public byte[] EmployeePhoto { get; set; }
public int? EmployeePhotoFileId { get; set; }
public byte[] ManagerPhoto { get; set; }
public int? ManagerPhotoFileId { get; set; }
public int? ScheduleId { get; set; }
public string AppVersion { get; set; }
public bool DeviceWasOffline { get; set; }
}
I've tried using the method syntax because i'm not to great at the query syntax:我尝试使用方法语法,因为我不擅长查询语法:
var query = filteredEmployees
.GroupJoin(filteredSchedules, e => e.FileNumber, s => s.FileNumber, (e, s) => new { Employee = e, Schedule = s})
.SelectMany(o => o.Schedule.DefaultIfEmpty(), (l, r) => new { l.Employee, Schedule = r })
.GroupJoin(filteredPunches, t => t.Schedule.Id, p => p.ScheduleId, (t, p) => new { t.Employee, t.Schedule, Punch = p })
.SelectMany(o => o.Punch.DefaultIfEmpty(), (l, r) => new { l.Employee, l.Schedule, Punch = r })
.Select(x => new {
FileNumber = x.Employee.FileNumber,
Name = x.Employee.FirstName,
ScheduleId = x.Schedule.Id,
StartTime = x.Schedule.StartTime,
EndTime = x.Schedule.EndDate,
ActualPunchTime = x.Punch?.TimeStamp
})
.ToList();
I've cut down the required amount of fileds for testing, but as far as i can tell it's what your after:我已经减少了测试所需的文件数量,但据我所知,这就是你所追求的:
ToString() : { FileNumber = 12345, Name = Lee, ScheduleId = 1, StartTime = 02/19/2021 00:00:00, EndTime = 02/19/2021 09:00:00, ActualPunchTime = }
ToString() : { FileNumber = 12345, Name = Lee, ScheduleId = 2, StartTime = 02/18/2021 00:00:00, EndTime = 02/19/2021 00:00:00, ActualPunchTime = 02/19/2021 21:08:48 }
ToString() : { FileNumber = 12345, Name = Lee, ScheduleId = 3, StartTime = 02/17/2021 00:00:00, EndTime = 02/18/2021 00:00:00, ActualPunchTime = }
ToString() : { FileNumber = 12345, Name = Lee, ScheduleId = 4, StartTime = 02/17/2021 00:00:00, EndTime = 02/18/2021 00:00:00, ActualPunchTime = }
ToString() : { FileNumber = 12345, Name = Lee, ScheduleId = 5, StartTime = 02/17/2021 00:00:00, EndTime = 02/18/2021 00:00:00, ActualPunchTime = }
ToString() : { FileNumber = 12346, Name = Bob, ScheduleId = 6, StartTime = 02/17/2021 00:00:00, EndTime = 02/18/2021 00:00:00, ActualPunchTime = 02/19/2021 21:08:48 }
My Test data:我的测试数据:
var filteredEmployees = new List<Employee> {
new Employee
{
Id = 1,
FileNumber = "12345",
FirstName = "Lee",
},
new Employee
{
Id = 2,
FileNumber = "12346",
FirstName = "Bob",
}
};
var filteredSchedules = new List<Schedule>
{
new Schedule {
Id = 1,
FileNumber = "12345",
StartTime = DateTime.Now.Date,
EndDate = DateTime.Now.Date.AddHours(9)
},
new Schedule {
Id = 2,
FileNumber = "12345",
StartTime = DateTime.Now.AddDays(-1).Date,
EndDate = DateTime.Now.AddDays(-1).AddHours(9).Date
},
new Schedule {
Id = 3,
FileNumber = "12345",
StartTime = DateTime.Now.AddDays(-2).Date,
EndDate = DateTime.Now.AddDays(-2).AddHours(9).Date
},
new Schedule {
Id = 4,
FileNumber = "12345",
StartTime = DateTime.Now.AddDays(-2).Date,
EndDate = DateTime.Now.AddDays(-2).AddHours(9).Date
},
new Schedule {
Id = 5,
FileNumber = "12345",
StartTime = DateTime.Now.AddDays(-2).Date,
EndDate = DateTime.Now.AddDays(-2).AddHours(9).Date
},
new Schedule {
Id = 6,
FileNumber = "12346",
StartTime = DateTime.Now.AddDays(-2).Date,
EndDate = DateTime.Now.AddDays(-2).AddHours(9).Date
},
};
var filteredPunches = new List<Punches>
{
new Punches {
Id = 1,
ScheduleId = 2,
TimeStamp = DateTime.Now
},
new Punches {
Id = 2,
ScheduleId = 6,
TimeStamp = DateTime.Now
}
};
You can view my fiddle here: https://dotnetfiddle.net/jpWRh8你可以在这里查看我的小提琴: https://dotnetfiddle.net/jpWRh8
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.