UPDATE September 18, 2013
There seems to be no easy way to do this. I support a solution that involves some extension to the Entity Framework.
If you want to see these features in the Entity Framework, vote for them on the user's voice site , perhaps here and here
There are several similar questions on SO, but I canโt find the question new and similar enough to get the answer I'm looking for.
If this sounds like information overload, go to the CV summary .
Background
I am writing a WebApi REST service to expose some pre-existing data through an OData endpoint. I am using EntitySetContoller<TEntity, TKey> to do all the work for me. In addition to the standard OData parameters that are routed and translated by the base class, I added some custom parameters to provide some functionality for my controller.
My database server is a MS SQL Server with a full text index in the [BigText] NVarChar[4000] column of the [BigText] NVarChar[4000] table.
I have one limitation, I have to use the Code First model.
// 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. }
Problem
How to implement the // return something special ... my example?
Obviously niave
return this.context.SomeEntities.Where(e => e.BigText.Contains(searchTerm));
completely incorrect, it consists of a WHERE type
[BigText] LIKE '%' + @searchTerm + '%'
This does not use full-text search, therefore it does not support complex search queries and, conversely, it performs horribly.
This approach
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();
It looks promising, actually uses full-text search and is quite functional. However, you will notice that DbSqlQuery , the type returned by the SqlQuery function, does not implement IQueryable . Here it is forced to the correct return type with the AsQueryable() extension, but this breaks the "composition chain." The only statement that will be executed on the server is the one specified in the code above. Any additional offers specified in the OData URL will be served on a web server that supports the API, without the use of indexes and specialized database-based functions.
In summary
What is the most appropriate way to access full-text search in MS SQL Server CONTAINSTABLE using the Entity Framework 5 Code First model and acquire a โcompositeโ result?
Do I need to write my own IQueryProvider ? Is there any way to expand EF?
I do not want to use Lucene.Net, I do not want to use the created database. Maybe I could add extra packages or wait for EF6, will this help?