2012-02-10 48 views
0

我想詢問下面的我的Linq解決方案是否是一個好的解決方案或者是否有更好的方法。我是使用Linq的新手,並且最熟悉MySQL。所以我一直在將我過去的項目之一從PHP轉換爲.NET MVC,並且正在嘗試學習Linq。我想知道是否有比我提出的更好的解決方案。優雅的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中,我用下面的查詢來獲取ealiest保留在每個maplocation與非空日期對於沒有任何位置有保留。

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查詢

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只是其中有變量相匹配的整型,字符串,雙人雙,日期,查詢字符串結果的類。有沒有簡單的方法來獲得一個列表,而不必做一個foreach並將結果傳遞給構造器重寫?或者我應該將它添加到ViewData並返回視圖?

+0

你使用實體框架?如果是這樣,你有外鍵,一些加入已經爲你完成。另外,您不能使用ToList將匿名類型強制爲聲明類型。您必須在選擇中使用該類型的新實例。 – JamieSee 2012-02-10 15:59:00

+0

@James謝謝你的回覆。是的,它使用實體框架。我對此也很陌生。我從來沒有在select中使用locAndResModel。所以看起來這應該在最後一個查詢中工作:'select new locAndResModel((int)loc.ID,(string)loc.name,(double)loc.Lat,(double)loc.Lng,res2!= null?(日期時間)res2.resDate:DateTime.MinValue,(字符串)usr2.name)' – Gamil 2012-02-10 17:25:16

回答

0

您將需要利用由實體框架執行的自動連接。試一試,讓我知道如果它做你想要的:

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) 
+0

除了我得到「指定的方法不支持」從MySQL.Data.Entity.SqlGenerator.Visit – Gamil 2012-02-16 17:27:53

+0

@Gamil一切似乎很好抱歉意識到我打亂並將這些元素從FirstOrDefault中移出。看看是否修復它。 – JamieSee 2012-02-16 22:04:21

+0

沒有。我注意到,當我把它放入VS.再次感謝您的幫助。我做了一些挖掘,似乎是MySQL和Entity Framework的一些東西。我已經看到了一些關於這個問題的文章,並且經常使用MSSQL而不是MySQL。所以我會在MSSQL中嘗試它(出於學術目的),並讓你知道這是怎麼回事。 – Gamil 2012-02-17 14:49:10

相關問題