c# - 为什么我的查询没有结果?

标签 c# asp.net sql-server linq asp.net-mvc-5

我想在我的数据库中选择可用的 spotId。我有这个方法:

public ActionResult ShowAvailableSpots(int Id, DateTime ArrivalDate, DateTime LeaveDate)
{
    var query2 = (from r in db.Reservations
                where (DbFunctions.TruncateTime(r.ArrivalDate) >= DbFunctions.TruncateTime(ArrivalDate)
                    && DbFunctions.TruncateTime(r.LeaveDate) <= DbFunctions.TruncateTime(LeaveDate))
                  select r.spot);

    ViewBag.StartingDate = ArrivalDate;
    ViewBag.EndingDate = LeaveDate;
    ViewBag.AvailableSpots = query2;

    ViewBag.CampingSpotId = new SelectList(query2, "CampingSpotId", "SpotName");

    return View();
}

我确定在给定的日期范围内没有预订,那为什么没有返回 spot id?

查询生成的输出如下:

SELECT
   [Extent2].[campingspotid] AS [CampingSpotId],
   [Extent2].[spotname]      AS [SpotName],
   [Extent2].[fieldname]     AS [FieldName],
   [Extent2].[surface]       AS [Surface],
   [Extent2].[wifi]          AS [Wifi],
   [Extent2].[water]         AS [Water],
   [Extent2].[sewer]         AS [Sewer],
   [Extent2].[reserved]      AS [Reserved],
   [Extent2].[booked]        AS [Booked],
   [Extent2].[spotprice]     AS [SpotPrice],
   [Extent2].[type]          AS [Type]   
FROM
   [dbo].[reservations] AS [Extent1]          
INNER JOIN
   [dbo].[campingspots] AS [Extent2]                  
      ON [Extent1].[campingspotid] = [Extent2].[campingspotid]   
WHERE
   (
      (
         CONVERT (DATETIME2, CONVERT(VARCHAR(255), [Extent1].[arrivaldate],                                  102), 102                     )            
      ) >= (
         CONVERT (DATETIME2, CONVERT(VARCHAR(255), @p__linq__0, 102), 102                   ) 
      ) 
   )          
   AND (
      (
         CONVERT (DATETIME2, CONVERT(VARCHAR(255), [Extent1].[leavedate],                                      102), 102)                
      )                    <= (
         CONVERT (DATETIME2, CONVERT(VARCHAR(255), @p__linq__1, 102                                             ), 102)                       
      ) 
   )

PS:我使用 TruncateTime 因为 this

编辑:这是我的预订模型:

public class Reservation
{
    [Key]
    public int ReservationId { get; set; }

    [DataType(DataType.Date)]
    public DateTime ArrivalDate { get; set; }

    [DataType(DataType.Date)]
    public DateTime LeaveDate { get; set; }
    //Vreemdesleutel van Plek

    public int CampingSpotId { get; set; }

    public virtual CampingSpot spot { get; set; }

}

这是我的露营地模型:

public class CampingSpot
{
    [Key]
    [Required(ErrorMessage = "Please select at least one CampingSpotID")]
    public int CampingSpotId { get; set; }
    public string SpotName { get; set; }  
}

新查询输出如下:SELECT CAST(NULL AS int) AS [C1], CAST(NULL AS datetime2) AS [C2], CAST(NULL AS datetime2) AS [C3], CAST(NULL AS int ) AS [C4], CAST(NULL AS int) AS [C5], CAST(NULL AS int) AS [C6] FROM (SELECT 1 AS X) AS [SingleRowTable1] WHERE 1 = 0

上面的输出是由这个查询生成的:

var res = db.Reservations.Where(c => DbFunctions.TruncateTime(c.ArrivalDate) >= DbFunctions.TruncateTime(ArrivalDate)
                                       && DbFunctions.TruncateTime(c.LeaveDate) <= DbFunctions.TruncateTime(LeaveDate)
                                       && c.CampingSpotId == null); 

最佳答案

我可以从您生成的 SQL 中看到,它正在 CampingSpots 上执行 FROM ReservationsINNER JOIN,您已经提到了您确保没有对该时间日期进行预订,因此没有结果...

编辑 1 根据您的评论,如果您想要所有没有预订的露营地,您想要做

FROM CampingSpots cs 
LEFT JOIN Reservations r 
WHERE r.ID IS NULL

在你的 Linq2Entitis 中,类似这样的东西:

    public class Reservation
    {
        public DateTime ArrivalDate { get; set; }
        public DateTime LeaveDate { get; set; }
    }

    public class CampingSpot
    {
        public virtual Reservation Reservation { get; set; }

    }
    public class TestClass
    {
        public void Test()
        {            
            var CampingSpots = new List<CampingSpot>().AsQueryable();

            var ArrivalDate = new DateTime();
            var LeaveDate = new DateTime();

            var res = CampingSpots.Where(c => DbFunctions.TruncateTime(c.ArrivalDate) >= DbFunctions.TruncateTime(ArrivalDate)
                                           && DbFunctions.TruncateTime(c.LeaveDate) <= DbFunctions.TruncateTime(LeaveDate)
                                           && c.Reservation == null)
                                 ).ToList();                
        }
    }

编辑 2

好的,您需要将 Reservation 作为导航属性添加到 CampingSpot 模型中。

public class CampingSpot
{
    [Key]
    [Required(ErrorMessage = "Please select at least one CampingSpotID")]
    public int CampingSpotId { get; set; }
    public string SpotName { get; set; }  

    public virtual int ReservationId { get; set; }
}

然后将您的 Controller 操作修改为:

        public ActionResult ShowAvailableSpots(int Id, DateTime ArrivalDate, DateTime LeaveDate)
        {
            var query2 = db.CampingSpots.Where(c => DbFunctions.TruncateTime(c.ArrivalDate) >= DbFunctions.TruncateTime(ArrivalDate)
                                           && DbFunctions.TruncateTime(c.LeaveDate) <= DbFunctions.TruncateTime(LeaveDate)
                                           && c.Reservation == null)
                                 ).ToList();

            ViewBag.StartingDate = ArrivalDate;
            ViewBag.EndingDate = LeaveDate;
            ViewBag.AvailableSpots = query2;

            ViewBag.CampingSpotId = new SelectList(query2, "CampingSpotId", "SpotName");

            return View();
        }

编辑 3

我刚刚注意到你在做什么。如果 camping Spots 没有 ArrivalDate 和 LeaveDate。您将需要获得该时间之间的预订,然后在 C# 中找出哪些日期实际上是免费的。所以是的,您的原始查询是正确的,但是您需要手动检查每个“天/期间”并计算它是否免费。如果您没有收到任何结果,则表示该露营地在整个期间都是免费的,因为它没有预订。如果它确实有预订,您要么需要返回说已预订,要么进行计算以找出确切的预订日期和免费预订日期。

编辑 4

            var query2 = db.CampingSpots
                .Where(c => !db.Reservations.Any(r => 
                               DbFunctions.TruncateTime(r.ArrivalDate) >= DbFunctions.TruncateTime(ArrivalDate)
                            && DbFunctions.TruncateTime(r.LeaveDate) <= DbFunctions.TruncateTime(LeaveDate)                 
                )).ToList();

编辑 5

你可能想要这样的东西,以防万一

1234567 < --- Day
|---|   < --- Reservation
  |---| < --- Query

这与编辑 4 不匹配,因为到达日期和离开日期不在两者之间。所以你需要检查以下内容:

            var query2 = db.CampingSpots
                .Where(c => !db.Reservations.Any(r => 
                               (DbFunctions.TruncateTime(r.ArrivalDate) >= DbFunctions.TruncateTime(ArrivalDate)
                            && DbFunctions.TruncateTime(r.ArrivalDate) < DbFunctions.TruncateTime(LeaveDate))    
                              ||
                               (DbFunctions.TruncateTime(r.LeaveDate) <= DbFunctions.TruncateTime(LeaveDate)
                            && DbFunctions.TruncateTime(r.LeaveDate) > DbFunctions.TruncateTime(ArrivalDate))             
                )).ToList();

关于c# - 为什么我的查询没有结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28843601/

相关文章:

c# - Entity Framework 插入新行而不是更新它们

c# - SqlCommand返回值参数

c# - Dapper/EF - 为什么当变量不在使用范围内时性能会提高

c# - 在 .Net 中获取实际的 dll 路径

asp.net - MVC3 和 ACS 声明身份

sql-server - 更新后 SQL Server 错误 : The token supplied to the function is invalid

sql-server - 解析TSQL脚本并返回表和列的使用情况

C# RabbitMQ 客户端线程安全

c# - 在 Excel 范围内指定列

C# - RadGrid - 如何手动调用 ItemDatabound 事件?