2009-11-13 5 views
4

У меня есть две таблицы, теги (tagid, postid, tagname) и сообщения (postid, name, ...)
теперь я хочу сделать запрос, который возвращает мне все сообщений с общим количеством тегов. нравится: я хочу, чтобы все сообщения, которые имеют asp.net тег И JQuerylinq запрос для системы тегов - поиск нескольких тегов

, как я сказал, количество тегов, чтобы искать является родовым

, как я могу сделать что-то подобное?

ТНХ

обновление 17.11.2009: есть одна проблема: отношение betwenn таблиц не существует, потому что мой первичный ключ на 2-х полей (для управления версиями), как я могу сделать это без связи? Im, использующий Linq To Entities

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

ответ

1

Я думаю, вы не можете использовать .Contains() с использованием EF 3.5, который я имел проблемы с. Я получил вокруг этого с помощью этого «где» расширение

'Contains()' workaround using Linq to Entities?

поместить это в статический класс, то вы могли бы использовать что-то вроде:

IQueryable<Post> PostsWithByTags(IEnumerable<string> tagNames) 
{ 
    var postIds = context.Tags.Select(t=>t.postid); 

    foreach (var tag in tagNames) 
    { 
     postIds = context.Tags 
        .WhereIn(t=> t.postid, postIds) 
        .Where(t=>t.tagname == tag); 
    } 

    return context.Tags.Where(t=> t.posId, postIds) 
} 

Я действительно думаю, что вы должны смотреть на имеющие отношения между ваши столы.

6

Вы не говорите, используете ли вы L2S, L2O, L2E или что. Итак, вот метод расширения, который работает для всех из них. Я делаю некоторые догадки о макете ваших объектов, поэтому вам, возможно, придется исправить некоторые из этих объектов.

public static IQueryable<Post> WhereHasAllTags(this IQueryable<Post> posts, IEnumerable<string> tags) 
{ 
    var q = posts; 
    foreach (var tag in tags) 
    { 
     q = q.Where(p => p.Tags.Any(t => t.Name == tag)); 
    } 
    return q; 
} 

Теперь можно использовать:

var filtered = Context.Posts.WhereHasAllTags(new [] { "asp.net", "jquery" }); 
+0

это похоже на то, что мне нужно, но есть одна проблема: отношение между таблицами не существует, потому что мой первичный ключ находится на 2 полях (для управления версиями), как я могу сделать это без отношения? (im using EF btw) – k0ni

+0

Трудно ответить, не видя метаданных. Хотите опубликовать его как отдельный вопрос с дополнительной информацией? –

+0

Вы можете просто «присоединиться» к EF, чтобы вы могли «подделать» отношения. –

4

Лучше смотреть в LinqKit динамически создавать предикаты. Это позволит вам объединить несколько предикатов вместе, так что вы просто пропустите теги, чтобы создать окончательное выражение.

Существуют особые соображения, если вы используете Entity Framework по сравнению с Linq2SQL, поэтому немного сложно опубликовать конкретный код, но примеров на этой странице должно быть достаточно, чтобы указать вам в правильном направлении.

+0

здесь, у вас есть свой первый upvote. –

1
IQueryable<Post> FilterByTags(IQueryable<Post> posts, IEnumerable<Tag> tags) 
{ 
    foreach (var tag in tags) 
    { 
     posts = posts.Where(post => post.Tags.Contains(tag)); 
    } 
    return posts; 
} 

IQueryable<Post> вы передаете будет иметь фильтры, добавленные к нему, чтобы убедиться, что он ссылается на каждый Tag в списке.

Это общая реализация которых может потребоваться настроить в зависимости от поставщика LINQ

+2

Вы понимаете, что этот код ничего не делает *? Это метод void с единственным побочным эффектом: перечисление «тегов». –

+0

Хорошая точка, было время, так как я использовал LINQ, это неизменно, не так ли. –

+0

То, что вас обмануло, - это не неизменность * per se *. Это отсроченное исполнение. Вызов 'Where' не будет выполнять какой-либо запрос, а вместо этого будет« создавать »запрос. Только когда вы перечислите его позже (либо с 'foreach',' ToList', 'ToArray', либо, возможно, что-то еще), запрос будет запущен. –

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