I’m trying to implement jqgrid search on MVC, following the interesting answer by @Oleg, regarding the question: ASP.NET MVC 2.0 Implementation of searching in jqgrid.
Actually I have a data repository based on EF & DBContext. Moreover, I have an entity with ‘calculated’ fields, I mean properties in DbSets that are calculated on the base of other fields.
I have two main problems, implementing the solution described in the first answer of the above link:
1st problem) The solution is based on ObjectQuery. I believe I have solved by creating a IObjectContextAdapter of my context and then casting with (ObjectQuery)…in my ignorance, I do not exactly know if this solution may be regarded as scalable or if there is a better solution…I am sure it exists, but it is beyond my knowledge!
2nd problem) At first query, the following EntitySqlException is raised: ‘Calculated’ is not a member of type ‘Models.Ticket’ in the currently loaded schemes
May you give me some kind of help or suggestion to above problems, please?
Here I put some parts of code I think could clarify:
PUBLIC ENUM
public enum StatiTT : int { A = 1, B = 2, C = 3, D = 4, E = 5, F = 6, G = 7 };
‘TICKET’ ENTITY
public class Ticket : IValidatableObject
{
public DateTime Data1 { get; set; }
public int StatoTicketID { get; set; }
....
public int Calculated // here's the problem...this is not a real field, it's a calculated property, as you see...
{
get
{
int mm=0;
DateTime Ora = DateTime.Now;
mm = (Data1 - Ora).Days*1440 + (Data1 - Ora).Hours * 60 + (Data1 - Ora).Minutes;
if (StatoTicketID > (int)StatiTT.DI && mm < 0) mm = 10000000;
return mm;
}
}
CONTEXT
public class dbContext : DbContext
{
public DbSet<Ticket> Tickets{ get; set; }
........
**REPOSITORY (actually not used in the above solution) **
public class myRepository : ImyRepository, IDisposable
{
private dbContext context;
public myRepository(dbContext context)
{
this.context = context;
}
public IQueryable<Ticket> ListTicketsQ()
{
return (from e in context.Tickets select e);
}
..........
CONTROLLER
public JsonResult jqIndex(string sidx, string sord, int page, int rows, bool _search, string filters)
{
var context = new dbContext();
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
var set = objectContext.CreateObjectSet<Ticket>();
var serializer = new JavaScriptSerializer();
Filters f = (!_search || string.IsNullOrEmpty(filters)) ? null : serializer.Deserialize<Filters>(filters);
ObjectQuery<Ticket> filteredQuery =
(f == null ? (ObjectQuery<Ticket>)set : f.FilterObjectSet((ObjectQuery<Ticket>)set));
filteredQuery.MergeOption = MergeOption.NoTracking; // we don't want to update the data
var totalRecords = filteredQuery.Count();
var pagedQuery = filteredQuery.Skip("it." + sidx + " " + sord, "@skip",
new ObjectParameter("skip", (page - 1) * rows))
.Top("@limit", new ObjectParameter("limit", rows));
// to be able to use ToString() below which is NOT exist in the LINQ to Entity
var queryDetails = (from item in pagedQuery
select new {
item.Calculated, // << THIS 'property' RAISES EntitySqlException
}).ToList();
.....
Any help would be appreciated. Thank you very much!
The best working solution to my problem has been resolved following the precious hints of Mr @Oleg: I moved the calculated properties into SQL Server, creating
Computed Columnsfor each property. Now it works fine and it is really fast!I lost more time trying to get working the calculated properties with ObjectSet, than create new computed columns directly in the db! As rightly pointed by Oleg, simple things are always the best!
Just another hint, for who’s using EF Codefirst: if you want to use computed properties, you must DROP COLUMNS after db creation and putting
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]attribute above property, as specified in here too.Thank you very much Oleg! I hope this solution may help other people!