2016-06-18 1 views
1

У меня есть 3 класса/таблицы: Car, User и UserVote (который является таблицей между двумя другими).Объединить внутреннее соединение и левое соединение в запросе Entity Framework

Например:

Car (id/name): 
1/Ford Focus 
2/Honda Civic 
3/Citroen C2 

User (id/ignoreUser): 
1/false 
2/true 
3/false 

UserVote (UserId/CarId) 
1/2 
1/3 
2/1 
3/2 

У меня есть метод, который получает верхние х автомобилей на основе количества голосов.

public IQueryable<Car> GetTopCars(int count) 
{ 
    return context.Car 
     .Include(car => car.UserVote) 
     .Where(car => car.UserVote.Count > 0) 
     .OrderByDescending(car => car.UserVote.Count) 
     .Take(count); 
} 

Этот код выглядит только за столом Автомобили и UserVote и не смотрит на поле ignoreUser на пользователя. Я пытаюсь обновить свой код Entity Framework, чтобы присоединиться к таблице User, но я не добился успеха. В конечном счете, я ищу, чтобы получить список автомобилей, заказанных по количеству UserVotes, за исключением тех, у которых IgnoreUser установлен в true. В приведенном выше примере я хотел бы, чтобы метод возвращал IQueryable в правильном порядке (Honda Civic then Citroen C2).

Я думаю, что хочу взять Автомобили, а затем присоединиться к этому пользователю с пользователем UserVote? Возможно ли это с Entity Framework?

Этот вопрос следует из рекомендации, приведенной в комментарии к previous question.

ответ

2

Если у вас есть User свойство навигации в вашем UserVote сущности то запрос может быть таким образом:

public IQueryable<Car> GetTopCars(int count) 
{ 
    return (from c in context.Car 
      let userVotes=car.UserVote.Where(uv=>!uv.User.IgnoreUser).Count() 
      where userVotes > 0 
      orderby userVotes 
      select c) 
      .Take(count); 
} 

Если вы хотите сделать это, используя только присоединиться к операции, то вы можете сделать это:

public IQueryable<Car> GetTopCars(int count) 
{ 
    return (from c in context.Car 
      let userVotes=(from uv in c.UserVotes 
          join u in context.Users on uv.UserId equals u.Id into users 
          where u=>!u.IgnoreUser 
          select u).Count() 
      where userVotes > 0 
      orderby userVotes 
      select c 
      ) 
      .Take(count); 
} 
+0

Когда я использую второй вариант с операциями объединения, я получаю дубликаты автомобилей - по одному на каждый голос. Кроме того, userVotes всегда равен тому, который, по моему мнению, связан с внутренним соединением? – psych

+0

Я попытаюсь исправить второй вариант. Можете ли вы не использовать первое решение, я уверен, что он работает. – octavioccl

+0

@psych, я исправил его, но я настоятельно рекомендую использовать первое решение, если можно. ИМХО это чище – octavioccl