2012-02-10 3 views
0

아래의 Linq 솔루션이 좋은 해결책인지 또는 더 좋은 방법이 있는지 물어보고 싶습니다. 나는 Linq를 처음 사용하고 MySQL에 익숙하다. 그래서 저는 PHP에서 .NET MVC로 이전 프로젝트 중 하나를 변환 해 왔으며 Linq를 배우려고합니다. 내가 생각해 낸 것보다 더 나은 해결책이 있는지 찾아야한다.독특한 데이터가있는 왼쪽 조인을위한 우아한 linq 솔루션

I가 다음과 같은 테이블 구조 :

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의에서, 내가 안 어떤 위치에 대한 null 이외의 날짜 각 maplocation에서 ealiest 예약을 얻기 위해 다음과 같은 쿼리를 사용하여 예약 해.

Linq에에서
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; 

는 비주얼 스튜디오는 자동으로 데이터베이스에 연결 한 후 구조의 대부분을 만드는, 나는

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()); 

그래서 SQL 쿼리에 다음 해당 때우기 이 쿼리를 수행하는 더 좋은 방법이 궁금합니다. 이와 동등한 제품입니까? 내가 따라야 할 모범 사례가 있습니까?

또 하나의 질문입니다. var에서이 문제를 해결하는 데 문제가 있습니다. 이 같은 위의 조각 locAndResModel에서

List<locAndResModel> locList = locAndRes.AsQueryable().ToList<locAndResModel>(); 

작동하지 않는 일을하는 것은 바로 INT, 문자열, 더블 더블, 날짜 시간, 쿼리 문자열 결과와 일치하는 변수가있는 클래스입니다. foreach를 수행하지 않고 결과를 생성자 오버라이드에 전달하지 않고 목록을 얻는 쉬운 방법이 있습니까? 아니면 그냥 ViewData에 추가하고 뷰를 반환해야합니까?

+0

Entity Framework를 사용하고 있습니까? 그렇다면 외래 키가 있습니다. 일부 참여는 이미 완료되었습니다. 또한 ToList를 사용하여 익명 형식을 선언 된 형식으로 강제 변환 할 수 없습니다. 선택한 유형의 새 인스턴스를 사용해야합니다. – JamieSee

+0

@James 답변 해 주셔서 감사합니다. 예, Entity 프레임 워크를 사용하고 있습니다. 나는 오히려 그렇게 새로운 것입니다. 내가 select 내에서 locAndResModel을 사용하지는 않겠다. 그래서 이것은 마지막 쿼리에서 작동해야합니다 :'select new locAndResModel ((int) loc.ID, (string) loc.name, (double) loc.Lat, (double) loc.Lng, res2! = null? (DateTime) res2.resDate : DateTime.MinValue, (문자열) usr2.name)' – Gamil

답변

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

MySQL.Data.Entity.SqlGenerator.Visit에서 오는 "지정된 메서드가 지원되지 않습니다."라는 것을 제외하면 모든 것이 잘 보입니다. – Gamil

+0

@Gamil 죄송합니다. typoed하고 FirstOrDefault의 parens 떠났다. 문제가 해결되는지 확인하십시오. – JamieSee

+0

아니요. 나는 그것을 VS에 넣을 때 그것을 알아 차렸다. 그리고 다시, 당신의 도움에 감사드립니다. 나는 파기를 조금 해봤 다. 그것은 MySQL과 Entity Framework에있는 것으로 보인다. 나는 문제에 대한 몇 개의 게시물을 보았고, 종종 MySQL이 아닌 MSSQL과 잘 작동 할 것이다. 그래서 MSSQL에서 (학업 목적으로) 시도해보고 어떻게 진행되는지 알려 드리겠습니다. – Gamil