2016-07-18 4 views
3

Прежде всего, я искал Google/SO, проверил несколько примеров, но я не успел написать правильное выражение Linq:LINQ к SQL: Выравнивание по левому краю на нескольких столбцах

Это как мой рабочий SQL-запрос выглядит следующим образом:

select * 
from Places p 
left join VoteLog v 
on p.Id = v.PlaceId 
and v.UserId = '076a11b9-6b14-4230-99fe-28aab078cefb' --demo userid 

Это моя попытка с помощью LINQ:

public IQueryable<Place> GetAllPublic(string userId) 
{ 
    var result = (from p in _db.Places 
       join v in _db.VoteLogs 
       on p.Id equals v.PlaceId // This works but doesn't fully reproduce my SQL query 
       // on new { p.Id, userId} equals new {v.PlaceId, v.UserId} -> Not ok 
       where p.Public == 1 
       select new 
       { 
        Id = p.Id, 
        UserId = p.UserId, 
        X = p.X, 
        Y = p.Y, 
        Titlu = p.Titlu, 
        Descriere = p.Descriere, 
        Public = p.Public, 
        Votes = p.Votes, 
        DateCreated = p.DateCreated, 
        DateOccured = p.DateOccured, 
        UserVoted = v.Vote 
       }) 
     .ToList() 
     .Select(x => new Place() 
     { 
      Id = x.Id, 
      UserId = x.UserId, 
      X = x.X, 
      Y = x.Y, 
      Titlu = x.Titlu, 
      Descriere = x.Descriere, 
      Public = x.Public, 
      Votes = x.Votes, 
      DateCreated = x.DateCreated, 
      DateOccured = x.DateOccured, 
      UserVoted = x.UserVoted 
     }).AsQueryable(); 
+0

Попробуйте http://stackoverflow.com/questions/373541/how-to -do-joins-in-linq-on-multiple-fields-in-single-join – MichaelMao

+0

Почему вы выбираете дважды? – user3185569

ответ

3

В запросе вы не сделали ни одного left join. Попробуйте это:

from p in _db.places 
join v in _db.VoteLogs 

//This is how you join by multiple values 
on new { Id = p.Id, UserID = userId } equals new { Id = v.PlaceId, UserID = v.UserID } 
into jointData 

//This is how you actually turn the join into a left-join 
from jointRecord in jointData.DefaultIfEmpty() 

where p.Public == 1 
select new 
{ 
    Id = p.Id, 
    UserId = p.UserId, 
    X = p.X, 
    Y = p.Y, 
    Titlu = p.Titlu, 
    Descriere = p.Descriere, 
    Public = p.Public, 
    Votes = p.Votes, 
    DateCreated = p.DateCreated, 
    DateOccured = p.DateOccured, 
    UserVoted = jointRecord.Vote 
    /* The row above will fail with a null reference if there is no record due to the left join. Do one of these: 
     UserVoted = jointRecord ?.Vote - will give the default behavior for the type of Uservoted 
     UserVoted = jointRecord == null ? string.Empty : jointRecord.Vote */ 
} 
+0

Ошибка Тип одного из выражений в предложении соединения неверен. Ошибка ввода типа в вызове «GroupJoin». –

+0

@Stefan - Это было потому, что тип/имена анонимных типов 'on' не совпадали. Попробуйте сейчас –

+0

На UserVoted = v.Vote: Ошибка Имя 'v' не существует в текущем контексте –

1

Вы должны использовать .DefaultIfEmpty() для выполнения присоединиться к левой. Затем вам нужно решить, что делать, если правая таблица создает нуль. Для этого вы можете использовать тернарный оператор (? :).

var result = 
    (from p in _db.Places 
    join v in _db.VoteLogs 
    on new { p.Id, userId } equals new { v.PlaceId, v.UserId } into LEFTJOIN 
    from result in LEFTJOIN.DefaultIfEmpty() 
    where p.Public == 1 
    select new 
    { 
     Id = p.Id, 
     UserId = p.UserId, 
     X = p.X, 
     Y = p.Y, 
     Titlu = p.Titlu, 
     Descriere = p.Descriere, 
     Public = p.Public, 
     Votes = p.Votes, 
     DateCreated = p.DateCreated, 
     DateOccured = p.DateOccured, 
     UserVoted = result == null ? null /* replace with your value */ : x.Vote 
    }).AsQueryable(); 

return result; 
1

Если ваша проблема назначения ключевых слов для этих нескольких условий соединения:

// on new { p.Id, userId} equals new {v.PlaceId, v.UserId} 

попробовать с

on new { a = p.Id, b = userId} equals new { a = v.PlaceId, b = v.UserId}