2013-03-19 2 views
2

У меня есть база данных, которая включает в себя один ко многим внешним ключом, напримерСоставьте это в одно утверждение?

Table {shop 
[Id] 
...} 

Table {user 
[Id] 
[Shop_id] 
[Archived] 
} 

У меня также есть метод, как показано ниже

public IEnumerable<shop> GetShopDetails(int shopId) 
{ 
    var foo = (from s in context.Shops 
    where s.Id = shopId 
    select s).ToList(); 

    return foo; 
} 

Как следствие этого, он будет возвращать все пользователи для это магазин. В большинстве случаев я только хочу, чтобы пользователи не архивировались.

Есть ли способ записать это в одно утверждение, поэтому я могу пройти, скажем, второй параметр includeArchived и использовать это, чтобы определить, верну ли я всех пользователей или только те, которые являются активными.

В настоящее время я могу заставить его работать либо путем добавления метода к моему объекту магазина, который возвращает подмножество пользователей, либо я могу загрузить магазин, получить его идентификатор, а затем создать отдельную коллекцию пользователей, которые содержат соответствующий fk, но любой метод кажется мне немного неуклюжим.

+0

Вам нужно сделать присоединиться: http://stackoverflow.com/questions/3217669/how-to-do-a-join-in- linq-to-sql-with-method-syntax – Nick

+3

Почему вы преобразовываете запрос в список? Почему бы просто не вернуть «IQueryable » и разрешить вызывающему устройству его далее фильтровать (на уровне базы данных), если они того пожелают? – Servy

+0

@Servy - опасность обучения EF из интернета. Я боюсь, я собираю плохие привычки из плохих уроков. – Matt

ответ

2

Просто условно добавить еще Where условие:

public IQueryable<user> GetShopUsers(int shopId, bool includeArchived = false) 
{ 
    var foo = from u in context.Users 
       where u.Shop_id = shopId 
       select u; 

    if(!includeArchived) 
     foo = foo.Where(u => !u.Archived); 

    return foo; 
} 
+0

Я могу нарушать правила EF или передовую практику, но мне также нужно отобразить некоторую информацию из магазина, поэтому я возвращаюсь в магазине, который содержит отфильтрованный список пользователей, а не только список пользователей. 2 таблицы уже соединены на fk, но я предполагаю, что мне нужно какое-то явное соединение или включить оператор, чтобы делать то, что мне нужно. Лучшее, что я до сих пор возвращает мне N копий магазина (подсчет для активных пользователей), каждый из которых касается всех пользователей. – Matt

+0

В этом случае вы можете взглянуть на [этот трюк] (http://stackoverflow.com/questions/12996617/filtering-navigation-property-in-eager-loading), посмотрите на второе предложение @ Botz3000 или просто сделайте один запрос для магазина и другой для неархивированных пользователей. –

0

Я думаю, это то, что вы хотите? Вы можете интегрировать другой логический параметр в свой запрос так же, как вы уже делали с shopId.

public IQueryable<user> GetUsers(int shopId, bool includeArchived) 
{ 
    return from user in context.Users 
      where user.Shop_id = shopId 
      where includeArchived || !user.Archived 
      select user; 
} 

UPDATE: Не уверен, что вы можете отфильтровать собственную коллекцию пользователей Shop Entity. Можно попробовать запрос построение анонимного объекта:

var foo = from s in context.Shops 
      where s.Id = shopId 
      select new { 
       Shop = s, 
       Users = s.Users.Where(u => includeArchived || !u.Archived) 
      }; 
+0

См. Выше комментарий :) – Matt

+0

@Matt Вы можете попытаться создать аномальный тип в своем запросе. См. Мое обновление. Не уверен, что он работает. – Botz3000

+0

Спасибо, я посмотрел на это, и я могу получить foo анонимным типом (если я его расширю, он вернет кортеж магазинов и пользователей.), Которые я не могу потом перевести обратно в дилерский центр, а также не могу развернуть пользователей когда читатель уже открыт. Думаю, что я пытаюсь сделать что-то, что нельзя сделать. (Или, по крайней мере, я пока не могу это понять.) Я продолжу делать это неуклюжим способом, пока я думаю, спасибо thoguh – Matt

Смежные вопросы