最近在做考勤系统时,由于不同的分公司的数据源在不同的服务器上,关联查询比较麻烦,因此想到了用Linq实现关联查询。
思路:查询各个考勤信息的dataTable,然后用Linq实现DataTable的多张表左关联查询。贴出来,与大家分享。
代码实现如下:
1.View显示:
/// <summary>
/// 考勤统计表-用于工资核算
/// </summary>
public class AttendanceCountVM
{
[Key]
public Guid Guid { get; set; }
[Display(Name = "姓名")]
public string Name { get; set; } //姓名
[Display(Name = "部门")]
public string Department { get; set; } //部门
[Display(Name = @"迟到/早退大于30分钟/次")]
public int LateMore { get; set; } //迟到/早退大于30分钟/次
[Display(Name = @"迟到/早退小于30分钟/次")]
public int LateLess { get; set; } //迟到/早退小于30分钟/次
[Display(Name = "单次打卡(上班未打卡)/次")]
public int SignIn { get; set; } //单次打卡(上班未打卡)/次
[Display(Name = "单次打卡(下班未打卡)/次")]
public int SignOut { get; set; } //单次打卡(下班未打卡)/次
[Display(Name = "未打卡/次")]
public int SignNo { get; set; } //未打卡/次
[Display(Name = "实际应出勤(H)")]
public int AttendanceTime { get; set; } //实际应出勤(H)
[Display(Name = "出差(H)")]
public int OutSide { get; set; } //出差(H)
[Display(Name = "事假(H)")]
public int AffairLeave { get; set; } //事假(H)
[Display(Name = "病假(H)")]
public int SickLeave { get; set; } //病假(H)
[Display(Name = "产前病事假(H)")]
public int AntenatalLeave { get; set; } //产前病事假(H)
[Display(Name = "产假或护理假(H)")]
public int MaternityLeave { get; set; } //产假或护理假(H)
[Display(Name = "婚假(H)")]
public int MaritalLeave { get; set; } //婚假(H)
[Display(Name = "丧假(H)")]
public int FuneralLeave { get; set; } //丧假(H)
[Display(Name = "年假(H)")]
public int AnnualLeave { get; set; } //年假(H)
[Display(Name = "公假(H)")]
public int PublicHoliday { get; set; } //公假(H)
[Display(Name = "其他(H)")]
public int Others { get; set; } //其他(H)
[Display(Name = "调休(H)")]
public int BreakOff { get; set; } //调休(H)
[Display(Name = "平时延长(H)")]
public int PeacetimeExtension { get; set; } //平时延长(H)
[Display(Name = "休息日(H)")]
public int RestDay { get; set; } //休息日(H)
[Display(Name = "法定节假日(H)")]
public int LegalHolidays { get; set; } //法定节假日(H)
[Display(Name = "加班折合调休时间(H)")]
public int TotalHours { get; set; } //加班折合调休时间(H)
}
Linq实现:
public List<AttendanceCountVM> GetAttendanceList(string StartDate, string EndDate, string Employee)
{
DataTable dtEmployee = CommUtils.GetUserList("", Employee);
DataTable dtSignRecord = this.GetSignRecord(StartDate, EndDate);
DataTable dtLeaveRecord = this.GetLeaveRecord(StartDate, EndDate);
DataTable dtOvertimeRecord = this.GetOverTimeRecord(StartDate, EndDate);
DataTable dtOutSideRecord = this.GetOutSideRecord(StartDate, EndDate);
//List<AttendanceCountVM> list = (from m in dtEmployee.AsEnumerable()
// join n in dtSignRecord.AsEnumerable()
// on m.Field<string>("UNAME") equals
// n.Field<string>("emp_fname") into mn
// from x in mn.DefaultIfEmpty()
// select new AttendanceCountVM
// {
// Name = m.Field<string>("UNAME").ToString(),
// Department = m.Field<string>("OName").ToString(),
// }).ToList();
var list = (from m in dtEmployee.AsEnumerable()
join n in dtSignRecord.AsEnumerable()
on m.Field<string>("UNAME") equals n.Field<string>("emp_fname") into mn
from x in mn.DefaultIfEmpty()
join o in dtOutSideRecord.AsEnumerable() on m.Field<decimal>("UserID") equals o.Field<Int32>("ApplyUserID") into mo
from y in mo.DefaultIfEmpty()
join p in dtLeaveRecord.AsEnumerable() on m.Field<decimal>("UserID") equals p.Field<Int32>("ApplyUserID") into mp
from z in mp.DefaultIfEmpty()
join q in dtOvertimeRecord.AsEnumerable() on m.Field<decimal>("UserID") equals q.Field<Int32>("ApplyUserID") into mq
from zx in mq.DefaultIfEmpty()
select new AttendanceCountVM
{
Guid = Guid.NewGuid(),
Name = m.Field<string>("UNAME").ToString(),
Department = m.Field<string>("OName").ToString(),
LateMore = x == null ? 0 : x.Field<Int32>("迟到或早退30分钟以上"),
LateLess = x == null ? 0 : x.Field<Int32>("迟到或早退30分钟以内"),
SignIn = x == null ? 0 : x.Field<Int32>("上班未打卡"),
SignOut = x == null ? 0 : x.Field<Int32>("下班未打卡"),
SignNo = 0,//n.Field<string>("").ToString(),
AttendanceTime = 176,// m.Field<string>("").ToString(),
OutSide = y == null ? 0 : y.Field<Int32>("TotalOutSide"),
AffairLeave = z == null ? 0 : z.Field<Int32>("事假"),
SickLeave = z == null ? 0 : z.Field<Int32>("病假"),
AntenatalLeave = z == null ? 0 : z.Field<Int32>("产前病事假"),
MaternityLeave = z == null ? 0 : z.Field<Int32>("产假或护理假"),
MaritalLeave = z == null ? 0 : z.Field<Int32>("婚假"),
FuneralLeave = z == null ? 0 : z.Field<Int32>("丧假"),
AnnualLeave = z == null ? 0 : z.Field<Int32>("年假"),
PublicHoliday = z == null ? 0 : z.Field<Int32>("公假"),
Others = z == null ? 0 : z.Field<Int32>("其他"),
BreakOff = z == null ? 0 : z.Field<Int32>("调休"),
PeacetimeExtension = zx == null ? 0 : zx.Field<Int32>("平时延长"),
RestDay = zx == null ? 0 : zx.Field<Int32>("休息日"),
LegalHolidays = zx == null ? 0 : zx.Field<Int32>("法定节假日"),
TotalHours = 0,// m.Field<Int32>("").ToString(),
}).ToList();
#region
// m.ItemArray.Concat(n.ItemArray.Skip(1)).Concat(o.ItemArray.Skip(1)).Concat(p.ItemArray.Skip(1)).Concat(q.ItemArray.Skip(1)).ToList());
//List<AttendanceCountVM> list = new List<AttendanceCountVM>();
//foreach (var item in items)
//{
// list.Add(new AttendanceCountVM
// {
// Guid = item.Guid,
// Name = item.Name,
// Department = item.Department,
// LateMore = item.LateMore,
// LateLess = item.LateLess,
// SignIn = item.SignIn,
// SignOut = int.Parse(item[7].ToString()),
// SignNo = int.Parse(item[7].ToString()),
// AttendanceTime = int.Parse(item[7].ToString()),
// OutSide = int.Parse(item[8].ToString()),
// AffairLeave = int.Parse(item[10].ToString()),
// SickLeave = int.Parse(item[11].ToString()),
// AntenatalLeave = int.Parse(item[12].ToString()),
// MaritalLeave = int.Parse(item[13].ToString()),
// FuneralLeave = int.Parse(item[14].ToString()),
// AnnualLeave = int.Parse(item[15].ToString()),
// PublicHoliday = int.Parse(item[16].ToString()),
// Others = int.Parse(item[17].ToString()),
// BreakOff = int.Parse(item[18].ToString()),
// PeacetimeExtension = int.Parse(item[19].ToString()),
// RestDay = int.Parse(item[20].ToString()),
// LegalHolidays = int.Parse(item[21].ToString()),
// TotalHours = int.Parse(item[21].ToString()),
// });
//}
#endregion
return list;
}
最终查询结果如下所示:
注意事项:关联查询时,要考虑到查询出来的Datarow是否为Null,因此,在给属性赋值时,首先要判断DataRow是否为空。
关于上述几个考勤查询的DataTable,可以参考本文的博客另一篇文章。考勤查询统计SQL