LINQ To SQL: фильтрация запросов по многим таблицам - PullRequest
1 голос
/ 11 февраля 2010

Я унаследовал этот проект от предыдущего парня, и в настоящее время я нахожусь в процессе переключения нескольких SQL-запросов, собранных из строки, на LINQ to SQL, и мне говорят, что это делает жизнь в .NET стоит жить. Однако у меня возникают проблемы с фильтрацией отношений «многие ко многим».

Система является интранет-менеджментом проекта. Первичный объект / таблица примечаний Project . Проект имеет множество Markets , которые используют промежуточную таблицу linkProjectMarkets , чтобы связать их. Там происходит много других вещей, но я могу позаботиться об этом, если я смогу понять эту проблему, все это похоже.

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

Суть схемы:

Проект : int id, ... (набор метаданных)
linkProjectMarkets : int projectId, int marketId
Market : int id, сводная строка

Все это, многое, многое другое, определено в файле dbml и сопровождающем сгенерированном коде. Для облегчения доступа между проект и market , проект имеет следующий метод добавления:

public partial class project
{
    public EntitySet<market> markets
    {
        get
        {
            return (EntitySet<market>)from lpm in this._linkProjectMarkets
                                      select lpm.market;
        }
        set
        {
            var set = (EntitySet<market>)from lpm in this._linkProjectMarkets
                                         select lpm.market;
            set.Assign(value);
        }
    }
}

Вот последний фрагмент кода, который я пытаюсь использовать для фильтрации набора всех проектов:

var projects = 
from p in db.projects
select p;

//MarketFilterList is an IEnumerable of market ids created from the checked checkboxes.
if(MarketFilterList.Count() > 0){
    foreach (int mid in MarketFilterList){
        projects = projects.Where(p => p.markets.Select(m => m.id).Contains(mid));
        /*
        Causes "Member access 'Int32 id' of 'PMIS2.market' not legal on type 
        'System.Data.Linq.EntitySet`1[PMIS2.market]."
        */
    }

}

Существует ряд других фильтров, которые нужно применить, поэтому я делаю это поэтапно, вместо одного оператора LINQ.

Я проверил код дизайнера; Рынок в linkProjectMarkets является публичным, а id - публичным на рынке. Это мой первый настоящий опыт работы с C # / .NET, так что, возможно, я просто не понимаю сообщение об ошибке. Извиняюсь, если я дал слишком много, недостаточно или неверную информацию. Пожалуйста, помогите!

P.S. Я уже попробовал LINQ to Entities, и у меня должна быть действительно веская причина, чтобы попробовать это снова.

Редактировать

Вот еще кое-что, что я попробовал:

projects = projects.Where(
    p => MarketFilterList.Intersect(from m in p.markets select m.id).Count() > 0
);

Тот сказал мне:

Локальная последовательность не может использоваться в реализации операторов запросов LINQ to SQL, кроме оператора Contains ().

Редактировать снова

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

projects = projects.Where(p => (from lpm in db.linkProjectMarkets
                                where MarketFilterList.Contains(lpm.marketId)
                                select lpm.project).Contains(p));

1 Ответ

1 голос
/ 11 февраля 2010

Я бы сделал следующее:

var projMarkLink = from lpm in db.linkProjectMarkets select lpm;

Установите IQueryable, затем в последующих строках добавьте фильтры:

foreach (int mid in MarketFilterList){
     projMarkLink = projMarkLink.Where(l => l.mid == mid);
}

Затем выберите нужный результат:

return (from lpm in projMarkLink
       from p in projMarkLink.Projects  
       select p).ToList();

Вы можете продвинуться на один шаг дальше и удалить цикл, прочитав этот вопрос стекопотока .

return (from lpm in projMarkLink
       from p in projMarkLink.Projects  
       where lpm.Contains(MarketFilterList)
       select p).ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...