简体   繁体   English

当它应该为真时,LINQ Query返回false

[英]LINQ Query returns false when it should be true

I have the following LINQ query written by a former developer and it isn't working when it should. 我有一个前开发人员编写的以下LINQ查询,它应该在它应用时不工作。

        public bool IsAvailable(Appointment appointment)
    {
        var appointments = _appointmentRepository.Get;
        var shifts = _scheduleRepository.Get;
        var city = _customerRepository.Find(appointment.CustomerId).City ?? appointment.Customer.City;

        const int durationHour = 1;

        DateTime scheduledEndDate = appointment.ScheduledTime.Add(new TimeSpan(durationHour, 0, 0));

        var inWorkingHours = shifts
            .Where(x =>
                //Check if any available working hours
                x.Employee.City == city &&

                x.ShiftStart <= appointment.ScheduledTime &&

                x.ShiftEnd >= scheduledEndDate &&

                //check if not booked yet
                !appointments
                    .Where(a =>
                        (appointment.Id == 0 || a.Id != appointment.Id) &&
                        a.Employee.Id == x.Employee.Id &&
                        (
                            (a.ScheduledTime <= appointment.ScheduledTime &&
                             appointment.ScheduledTime <= EntityFunctions.AddHours(a.ScheduledTime, durationHour)) ||
                            (a.ScheduledTime <= scheduledEndDate &&
                             scheduledEndDate <= EntityFunctions.AddHours(a.ScheduledTime, durationHour))
                            ))
                    .Select(a => a.Employee.Id)
                    .Contains(x.Employee.Id)

            );

        if (inWorkingHours.Any())
        {
            var assignedEmployee = inWorkingHours.FirstOrDefault().Employee;
            appointment.EmployeeId = assignedEmployee.Id;
            appointment.Employee = assignedEmployee;
            return true;
        }
        return false;
    }

CLASSES CLASSES

    public class Appointment
{
    [Key]
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public virtual Customer Customer { get; set; }
    public DateTime ScheduledTime { get; set; }
    public int? EmployeeId { get; set; }
    public virtual Employee Employee { get; set; }
}

public class Customer
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string Province { get; set; }
    public string PostalCode { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
    public virtual string Fullname { get { return FirstName + " " + LastName; } }

    public Customer(){ }
}

public class Employee
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string Province { get; set; }
    public string PostalCode { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
    public virtual string Fullname { get { return FirstName + " " + LastName; } }

    public Employee() { }
}

public class Shift
{
    [Key]
    public int Id { get; set; }

    public DateTime ShiftStart { get; set; }
    public DateTime ShiftEnd { get; set; }
    public int EmployeeId { get; set; }
    public virtual Employee Employee { get; set; }
}

The query is suppose to handle the following scenarios 该查询假设处理以下场景

  1. Given An Appointment With A ScheduledTime Between A ShiftStart and ShiftEnd time But Does not match any employees in same city - (Return true) 给出在ShiftStart和ShiftEnd时间之间的预定时间的约会但是不匹配同一城市的任何员工 - (返回true)
  2. Given An Appointment With A ScheduledTime Between A ShiftStart and ShiftEnd time AND Employee for that shift is in the same city as the customer (Return True AND Assign to the employee) 在ShiftStart和ShiftEnd时间之间预约时间的预约和该班次的员工与客户在同一个城市(返回True并分配给员工)

If the customer is NOT in the same city as an employee we assign the appointment as "Unassigned" as along as the scheduledTime is within an of the employees shift start/end times 如果客户与员工不在同一个城市,我们将约会分配为“未分配”,因为预定时间在员工班次开始/结束时间之内

If the customer is in the same city as an employee we assign the appointment to one of the employees (firstOrdefault) and occupy that timeslot. 如果客户与员工在同一个城市,我们会将约会分配给其中一个员工(firstOrdefault)并占用该时间段。

Appointments CAN NOT overlap (Assigned Ones). 约会不能重叠(指定的人)。 Unassigned can't overlap each other. 未分配不能相互重叠。

This query use to work (I've been told). 这个查询用于工作(我被告知)。 But now it doesn't and I have tried refactoring it and various other paths with no luck. 但现在它没有,我已经尝试重构它和各种其他路径没有运气。 I am now on week two and just don't know where the issue in the query is or how to write it. 我现在在第二周,只是不知道查询中的问题在哪里或如何编写它。

Let me know if I need to post anything further. 如果我需要进一步发布,请告诉我。 I have verified appointments, shifts, city all populate with valid data so the issue doesn't appear to be with null or missing data. 我已经验证了约会,轮班,城市都填充了有效数据,因此问题似乎没有空或缺少数据。

First of all, it is not 100% clear what do you mean by "This query use to work (I've been told). But now it doesn't". 首先,它不是100%明确你的意思是什么“这个查询用来工作(我被告知)。但现在它没有”。 Could you please provide some cases which show how it "doesn't work"? 你能否提供一些案例,说明它“不起作用”?

From my point of view the query looks almost right, but I guess there are some strange things. 从我的观点来看,查询看起来几乎是正确的,但我猜有些奇怪的事情。 Let's look on this piece of code: 让我们看看这段代码:

!appointments
    .Where(a =>
        (appointment.Id == 0 || a.Id != appointment.Id) &&
        a.Employee.Id == x.Employee.Id &&
        (
            (a.ScheduledTime <= appointment.ScheduledTime &&
            appointment.ScheduledTime <= EntityFunctions.AddHours(a.ScheduledTime, durationHour)) ||
            (a.ScheduledTime <= scheduledEndDate &&
            scheduledEndDate <= EntityFunctions.AddHours(a.ScheduledTime, durationHour))
         ))
    .Select(a => a.Employee.Id)
    .Contains(x.Employee.Id)

In the WHERE condition besides everything else you filter by the a.Employee.Id == x.Employee.Id . 在WHERE条件中,除了您通过a.Employee.Id == x.Employee.Id过滤的所有内容。 It means that the collection after the WHERE clause will contain only appointments of the single employee. 这意味着WHERE子句之后的集合将仅包含单个员工的约会。 So I guess we can rewrite this part to: 所以我想我们可以将这部分重写为:

!appointments.Any(a =>
    (appointment.Id == 0 || a.Id != appointment.Id) &&
    a.Employee.Id == x.Employee.Id &&
    (
        (a.ScheduledTime <= appointment.ScheduledTime &&
        appointment.ScheduledTime <= EntityFunctions.AddHours(a.ScheduledTime, durationHour)) ||
        (a.ScheduledTime <= scheduledEndDate &&
        scheduledEndDate <= EntityFunctions.AddHours(a.ScheduledTime, durationHour))
     ))

Another issue that might be: comparing of start/end dates. 另一个问题可能是:比较开始/结束日期。 In the code above you are checking the following: 在上面的代码中,您将检查以下内容:

.........[----------------]...........
               ^^^^^^
               ||||||
      start date and end date 
        not in this interval

So you check: 所以你检查:

  • that the start date (of new appointment) is not somewhere during an another appointment 在另一个约会期间,开始日期(新约会)不在某处
  • and the end date (of new appointment) is not somewhere during an another appointment 并且在另一个约会期间,结束日期(新约会)不在某处

It means that you will not catch the following situation: 这意味着您不会遇到以下情况:

.........[----------------]...........
     ^                           ^    
     |                           |    
 start date                  end date 

which is also unacceptable. 这也是不可接受的。 But according to your code const int durationHour = 1; 但是根据你的代码const int durationHour = 1; . So every meeting lasts for one hour and this braking situation should not be a problem for you. 所以每次会议都持续一个小时,这种制动情况对你来说应该不是问题。

Anyway, some kind of sample data where the code is braking down will be great. 无论如何,某些代码被制动的样本数据将是很好的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM