2013-10-26 46 views
0

我有以下開發人員編寫的以下LINQ查詢,並且它在應該時不工作。LINQ查詢在應該爲true時返回false

 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

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; } 
} 

查詢是假設來處理以下場景

  1. 考慮約見一個ShiftStart和ShiftEnd時間之間的ScheduledTime但不匹配在同任何員工城市 - (返回值爲)
  2. 給定約會ShiftStart和ShiftEnd之間的ScheduledTime時間AND Employee for這種轉變是在同一個城市作爲客戶(返回True,並分配給該僱員)

如果客戶是不是在同一個城市作爲員工,我們分配任命爲「未分配」沿作爲scheduledTime在員工輪班開始/結束時間內

如果客戶與員工位於同一城市,我們將約會分配給其中一個員工(firstOrdefault)並佔用該時間段。

約會不能重疊(已分配的一個)。未分配不能相互重疊。

此查詢用於工作(我已被告知)。但現在它並沒有,我試圖重構它和其他各種途徑,沒有運氣。我現在在第二週,只是不知道查詢中的問題在哪裏或如何編寫它。

讓我知道如果我需要發佈任何進一步的東西。我已經驗證了約會,班次,城市都填充了有效的數據,因此問題似乎沒有空或缺少數據。

+2

有些東西在發佈這樣的問題時有所幫助,其中包括此代碼中涉及的其他類型的基本定義。員工,任命,城市等 –

+0

我應該爲Employee,Appointment添加域類嗎? Repository類是實體框架的包裝,它是通用的)。 – devfunkd

+0

是的,我至少可以看到Employee,Appointment,Shift,City類型,以及您沒有提供的EntityFunctions.AddHours方法,爲了簡潔和相關性,您可以省略代碼中未使用的成員。 –

回答

2

首先,它不是100%清楚你的意思是「這個查詢用於工作(我已被告知),但現在它不」。您能否提供一些顯示「不起作用」的案例?

從我的角度來看,查詢看起來幾乎是正確的,但我想有一些奇怪的事情。讓我們來看看在這一段代碼:

!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) 

在別的不說,你在a.Employee.Id == x.Employee.Id過濾WHERE條件。這意味着WHERE子句後面的集合將只包含單個員工的約會。所以我想我們可以將這部分改寫爲:

!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)) 
    )) 

另一個問題可能是:比較開始/結束日期。在上面的代碼要檢查以下內容:

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

所以你檢查:

  • 那(新任命的)的開始日期是不顯山露水的另一個約會
  • 和結束日期時(新的約會)不是在另一個約會

這意味着你不會遇到以下情況:

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

這也是不可接受的。但根據你的代碼const int durationHour = 1;。所以每次會議持續一個小時,這種制動情況對你來說不應該是一個問題。

無論如何,代碼制動下來的某種樣本數據會很好。

相關問題