我想询问下面的Linq解决方案是否是一个好的解决方案,或者是否有更好的方法。我是使用Linq的新手,我最熟悉MySQL。所以我一直在将我过去的一个项目从PHP转换为.NET MVC,并且正在尝试学习Linq。我想知道是否有比我想出的更好的解决方案。
我有以下表结构:
CREATE TABLE maplocations (
ID int NOT NULL AUTO_INCREMENT,
name varchar(35) NOT NULL,
Lat double NOT NULL,
Lng double NOT NULL,
PRIMARY KEY (ID),
UNIQUE KEY name (name)
);
CREATE TABLE reservations (
ID INT NOT NULL AUTO_INCREMENT,
loc_ID INT NOT NULL,
resDate DATE NOT NULL,
user_ID INT NOT NULL,
PRIMARY KEY (ID),
UNIQUE KEY one_per (loc_ID, resDate),
FOREIGN KEY (user_ID) REFERENCES Users (ID),
FOREIGN KEY (loc_ID) REFERENCES MapLocations (ID)
);
CREATE TABLE Users (
ID INT NOT NULL AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
email VARCHAR(50) NOT NULL,
pass VARCHAR(128) NOT NULL,
salt VARCHAR(5) NOT NULL,
PRIMARY KEY (ID),
UNIQUE KEY unique_names (name),
UNIQUE KEY unique_email (email)
);
在MySQL中,我使用以下查询在每个maplocation获取最早的预留,并且对于没有预订的任何位置都使用非null日期。
SELECT locs.*, if(res.resDate,res.resDate,'0001-01-01') as resDate, res.Name as User
FROM MapLocations locs
LEFT JOIN (
SELECT loc_ID, resDate, Name
FROM Reservations, Users
WHERE resDate >= Date(Now())
AND user_ID = Users.ID
ORDER BY resDate
) res on locs.ID = res.loc_ID
group by locs.ID
ORDER BY locs.Name;
在Linq中,Visual Studio在连接到数据库后自动创建了大部分结构,我提出了以下与SQL Query等效的内容
var resList = (from res in Reservations
where res.ResDate >= DateTime.Today
select res);
var locAndRes =
(from loc in Maplocations
join res in resList on loc.ID equals res.Loc_ID into join1
from res2 in join1.DefaultIfEmpty()
join usr in Users on res2.User_ID equals usr.ID into join2
from usr2 in join2.DefaultIfEmpty()
orderby loc.ID,res2.ResDate
select new {
ID = (int)loc.ID,
Name = (string)loc.Name,
Lat = (double)loc.Lat,
Lng = (double)loc.Lng,
resDate = res2 != null ?(DateTime)res2.ResDate : DateTime.MinValue,
user = usr2 != null ? usr2.Name : null
}).GroupBy(a => a.ID).Select(b => b.FirstOrDefault());
所以,我想知道是否有更好的方法来执行此查询? 这些是等价的吗? 我应该遵循哪些良好做法?
另外,还有一个问题,我在从var
到列表时遇到这个问题。做这样的事情不起作用
List<locAndResModel> locList = locAndRes.AsQueryable().ToList<locAndResModel>();
在上面的代码片段中,locAndResModel
只是一个类,它具有匹配int,string,double double,DateTime,查询字符串结果的变量。是否有一种简单的方法来获取列表而无需执行foreach并将结果传递给构造函数覆盖?或者我应该将它添加到ViewData并返回View?
答案 0 :(得分:0)
您将希望利用Entity Framework执行的自动连接。尝试一下,让我知道它是否符合您的要求:
var locAndRes = from maplocation in MapLocations
let earliestReservationDate = maplocation.Reservations.Min(res => res.resDate)
let earliestReservation = (from reservation in mapLocation.Reservations
where reservation.resDate == earliestReservationDate && reservation.resDate >= DateTime.Today
select reservation).FirstOrDefault()
select new locAndResModel( maplocation.ID, maplocation.name, maplocation.Lat, maplocation.Lng, earliestReservation != null ? earliestReservation.resDate : DateTime.MinValue, earliestReservation != null ?earliestReservation.User.name : null)