For*_*rza 1 c# linq sql-server asp.net 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();
}
Run Code Online (Sandbox Code Playgroud)
我确定在给定的日期范围内没有预订,那么为什么没有返回现场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)
)
)
Run Code Online (Sandbox Code Playgroud)
PS:因为这个我使用TruncateTime
编辑:这是我的预订模型:
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; }
}
Run Code Online (Sandbox Code Playgroud)
这是我的campingspot模型:
public class CampingSpot
{
[Key]
[Required(ErrorMessage = "Please select at least one CampingSpotID")]
public int CampingSpotId { get; set; }
public string SpotName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
新的queryoutput看起来像: 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);
Run Code Online (Sandbox Code Playgroud)
我可以从你生成的SQL看到,这是做一个FROM Reservations有INNER JOIN上CampingSpots,和你提到你做肯定有肛门预订这段时间日期,因此没有结果...
根据您的评论编辑1 AS,如果您想要所有您没有预订的露营地,您想要这样做
FROM CampingSpots cs
LEFT JOIN Reservations r
WHERE r.ID IS NULL
Run Code Online (Sandbox Code Playgroud)
在你的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();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑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; }
}
Run Code Online (Sandbox Code Playgroud)
然后将Controller Action修改为:
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();
}
Run Code Online (Sandbox Code Playgroud)
编辑3
我刚刚注意到你在做什么.如果露营点没有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();
Run Code Online (Sandbox Code Playgroud)
编辑5
你可能想要这样的东西,以防万一
1234567 < --- Day
|---| < --- Reservation
|---| < --- Query
Run Code Online (Sandbox Code Playgroud)
这与编辑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();
Run Code Online (Sandbox Code Playgroud)