ОБНОВЛЕНИЕ 18 сентября 2013
Похоже, что нет простого способа сделать это. Я поддерживаю решение, которое предполагает некоторое расширение для Entity Framework.
Если вы хотите увидеть эти функции в Entity Framework, проголосуйте за них на голосовом сайте пользователя, возможно здесь и здесь
Есть несколько аналогичных вопросов по SO, но я не могу найти вопрос новый и достаточно похожий, чтобы получить ответ, который я ищу.
Если это похоже на информационную перегрузку, перейдите к В резюме.
Фон
Я пишу службу WebApi REST, чтобы выставить некоторые ранее существовавшие данные через конечную точку OData. Я использую EntitySetContoller<TEntity, TKey>
, чтобы сделать для меня всю работу. Помимо стандартных параметров OData которые маршрутизируются и транслируются базовым классом, я добавил некоторые пользовательские параметры, чтобы обеспечить определенную функциональность для мой контроллер.
Мой сервер базы данных - это MS SQL Server с полным текстовым индексом в столбце [BigText] NVarChar[4000]
таблицы [SomeEntity]
.
У меня есть одно ограничение, Я должен использовать модель Code First.
// Model POCO
public class SomeEntity
{
public int Id { get; set; }
public string BigText { get; set; }
}
// Simple Controller
public class SomeEntityController : EntitySetController<SomeEntity, int>
{
private readonly SomeDbContext context = new SomeDbContext();
public override IQueryable<SomeEntity> Get()
{
var parameters = Request.GetQueryNameValuePairs()
.ToDictionary(p => p.Key, p => p.Value);
if (parameters.ContainsKey("BigTextContains")
(
var searchTerms = parameters["BigTextContains"];
// return something special ...
)
return this.context.SomeEntities;
}
// ... The rest is omitted for brevity.
}
Проблема
Как реализовать часть // return something special ...
моего примера?
Очевидно, что niave
return this.context.SomeEntities.Where(e =>
e.BigText.Contains(searchTerm));
полностью неверен, он состоит из предложения WHERE
типа
[BigText] LIKE '%' + @searchTerm + '%'
Это не использует полнотекстовый поиск, поэтому не поддерживает сложные поисковые запросы и, наоборот, выполняет ужасно.
Этот подход,
return this.context.SomeEntities.SqlQuery(
"SELECT E.* FROM [dbo].[SomeEntity] E " +
"JOIN CONTAINSTABLE([SomeEntity], [BigText], @searchTerm) FTS " +
" ON FTS.[Key] = E.[Id]",
new object[] { new SqlParameter("@searchTerm", searchTerm) })
.AsQueryable();
Выглядит многообещающе, на самом деле использует полнотекстовый поиск и вполне функциональный. Однако вы заметите, что DbSqlQuery
, тип, возвращаемый функцией SqlQuery
, не реализует IQueryable
. Здесь он принуждается к правильному типу возврата с расширением AsQueryable()
, но это нарушает "цепочку композиции". Единственный оператор, который будет выполняться на сервере, - это тот, который указан в приведенном выше коде. Любые дополнительные предложения, указанные в URL-адресе OData, будут обслуживаться на веб-сервере, поддерживающем API, без использования индексов и специализированных функций, основанных на базе базы данных.
В резюме
Каков наиболее целесообразный способ доступа к полнотекстовому поиску в MS SQL Server CONTAINSTABLE
с помощью модели Entity Framework 5 Code First и приобретения "композитный" результат?
Нужно ли писать собственный IQueryProvider
? Можно ли каким-то образом расширить EF?
Я не хочу использовать Lucene.Net, я не хочу использовать созданную базу данных. Возможно, я мог бы добавить дополнительные пакеты или подождать EF6, это поможет?