why the date conversion is not working in linq - c#

I am new to mvc i had problem with following code it is throwing an exception:
LINQ to Entities does not recognize the method 'System.String ToString(System.DateTime)' method, and this method cannot be translated into a store expression.
public ActionResult JobSearchList(PostJobModel model)
{
try
{
if (Session["USER_ID"] != null)
{
var subscriber_Id = RL_Constants.RES_ID;
var company_Id = RL_Constants.COMP_ID;
var resource_Typa = RL_Constants.RES_TYPE;
var jobPostDetails = (from jobPost in reslandentity.JOB_POSTING
where jobPost.COMP_ID == RL_Constants.COMP_ID
select new PostJobModel
{
POST_DT=Convert.ToString(jobPost.POST_DT),
POST_END_DT=Convert.ToString(jobPost.POST_END_DT),
POSITIONS_CNTS=Convert.ToString(jobPost.POSITIONS_CNT),
JOB_TYPE = jobPost.JOB_TYPE,
SKILLS = jobPost.SKILLS,
DURATION = jobPost.DURATION,
CATEGORY=jobPost.CATEGORY,
PREREQUISITES = jobPost.PREREQUISITES,
LOCATION=jobPost.LOCATION,
RATE=jobPost.RATE,
PERKS = jobPost.PERKS,
CONTACT_PERSON=jobPost.CONTACT_NAME,
CONTACT_EMAIL=jobPost.CONTACT_INFO,
CONTACT_PHONE=jobPost.CONTACT_INFO,
POST_TITLE=jobPost.TITLE,
DESCRIPTION=jobPost.DESCR
}).ToList();
model.GetJobPostDetails = jobPostDetails;
}
return View(model);
}
catch (Exception ex)
{
throw ex;
}
}

The error is pretty self explantory, ToString is not supported by the LINQ provider therefore you can't use it in a query.
Pull down the raw data and perform your conversions in memory.
var jobPostDetails = reslandentity.JOB_POSTING
.Where(x => x.COMP_ID == RL_Constants.COMP_ID)
.AsEnumerable() // materialize query, Select will be performed in memory
.Select(x => new {
POST_DT = x.POST_DT.ToString(),
POST_END_DT = x.POST_END_DT.ToString(),
POSITIONS_CNTS = x.POSITIONS_CNT.ToString(),
...
})
.ToList();
AsEnumerable will switch the context from IQueryable<T> to IEnumerable<T> therefore allows for CLI-specific methods to be called as part of the query. The query will still only be materialized after ToList is called as AsEnumerable retains delayed execution.

Take a look at SqlFunctions when trying to convert something inside a LINQ Query.
SqlFunctions.DateName("dd", jobPost.POST_DT) +
SqlFunctions.DateName("mm", jobPost.POST_DT) +
SqlFunctions.DateName("yyyy", jobPost.POST_DT) +
This functions can also be used inside where clauses etc.

Related

Converting linq select into model, LINQ to Entities does not recognize the method, and this method cannot be translated into a store expression

Hi I i'm doing this linq expression in an web api but then it gives this error
LINQ to Entities does not recognize the method 'WebApplicationAPI.Models.Registo convertToRegisto(WebApplicationAPI.Models.TBS0017)' method, and this method cannot be translated into a store expression.
Here's the code:
var tBS0017 = from row in db.TBS0017
where row.Cartao == cartao && row.Data == data
var teste = tBS0017.Select(x => convertToRegisto(x));
public Registo convertToRegisto(TBS0017 x)
{
string term = db.ba_terminal.Where(y => "00"+y.terminal_id.ToString() == x.CodTerminal).Select(y => y.terminal_name).ToString();
string emp = db.TG0006.Where(y => "00"+y.IdCompanhia.ToString() == x.IdCompanhia.ToString()).Select(y => y.DsCompanhia).ToString();
Registo r = new Registo() { Cartao = x.Cartao, Data = x.Data, Hora = x.Hora, Local = term, Empresa = emp };
return r;
}
Bring tBS0017 back into memory with ToList()
var results = tBS0017.ToList()
.Select(x => convertToRegisto(x));
However, this has some serious flaws.
For every element in tBS0017, you are doing 2 more db query's. You should really be doing this in the one query and projecting to Registo
The issue is that using Linq to Entities tries to convert your C# code into equivalent SQL which can run your query. There is no function "convertToRegisto" in SQL so this gives you an exception.
You can solve the issue by using ToList() to bring the result of the query into memory first. Then you're able to use your methods in the Select.
var teste = tBS0017
.ToList()
.Select(x => convertToRegisto(x));
You can not convert int value from linq to sql. You must use the sql function that convert int to string values. On the other hand, in memory handling is quite heavy operation
e.g
string term = db.ba_terminal.Where(y => "00"+
SqlFunctions.StringConvert((double)y.terminal_id) ==
x.CodTerminal).Select(y => y.terminal_name).ToString();

Reusing Base Linq Query from one method to another

I am trying to remove duplicate code throughout my project and I am at a standstill trying to figure this out. What I am trying to do is create a base linq query that will be reused to add things like Where, Take...etc in multiple different methods.
public IQueryable<Object> FooLinq(int id)
{
using (var ctx = new dbEntities())
{
var results =
(from account in ctx.account
join memberProducts in ctx.tblMemberProducts on account.Id equals memberProducts.AccountId
orderby account.date descending
select new{account,memberProducts}).ToList();
return results;
}
}
So that would be by base query above and I would have a seperate method that would reuse VioLinq but this time would use a where clause in it.
public List<IncomingViolations> Foo1(int id)
{
//Linq query FooLinq() where Name == "Bob"
}
You'll need to do two things:
Return the query prior to materializing it.
Make sure the context is still in scope when the final query is materialized.
These two requirements will play off each other somewhat, and there are a number of approaches you can take to meet them.
For example, you could make your method take the context as a parameter, forcing the caller to provide it and manage its lifecycle.
public IQueryable<AccountInfo> FooLinq(DbEntities ctx, int id)
{
return
from account in ctx.account
orderby account.date descending
select new AccountInfo()
{
Name = account.Name,
Mid = account.MemberID,
Date = account.Date,
Address = account.Address,
};
}
public List<IncomingViolations> Foo1(int id)
{
using(var ctx = new dbEntities())
{
//Linq query FooLinq() where Name == "Bob"
return FooLinq(ctx).Where(v => v.Name == "Bob").ToList();
}
}
You could alternatively inject the context as a constructor-injected dependency, and use a DI framework to manage the context's lifecycle.
You can do it as Queryable then add conditions to it.
For example:
public List<account> GetAccountsByName(string name, bool usePaging, int offset = 0, int take = 0) {
var query = GetMyQuery();
query = query.Where(x => x.Name == name);
query = query.OrderBy(x => x.Name);
if(usePaging) {
query = query.Take(take).Skip(offset);
}
query = PrepareSelectForAccount(query);
return query.ToList(); .
}
public IQueryable<account> GetMyQuery(){
return ctx.account.AsQueryable();
}
public IQueryable<account> PrepareSelectForAccount(IQueryAble<account> query){
return query.Select(select new AccountInfo()
{
Name = account.Name,
Mid = account.MemberID,
Date = account.Date,
Address = account.Address,
}
);
}
Sure, but don't call .ToList(), and return IQueryable<T> instead of List<T>. LINQ is based on the concept of deferred execution which means the query is not actually performed until the enumerable is iterated over. Until then, all you have done is built an object which knows how to do the query when the time comes.
By returning an IQueryable<T> from a function that sets up the "basic query," you are then free to tack on additional LINQ methods (such as .Where() or .Take()) to produce a modified query. At this point you are still simply setting up the query; it is actually performed only when you iterate over the enumerable, or call something like .ToList() which does that for you.

Get result function in LINQ without translate to store expression

I need to get result from a function that it need to run in LINQ query. This result bind to grid but in run time I encounter with this error:
LINQ to Entities does not recognize the method 'System.String
GetName(System.Type, System.Object)' method, and this method cannot be
translated into a store expression.
This is my Code:
public IQueryable GetForRah_CapacityList(XQueryParam param)
{
var result = (from x in Data()
select new
{
Rah_CapacityId = x.Rah_CapacityId,
Rah_CapacityName = x.Rah_CapacityName,
Rah_St = Enum.GetName(typeof(Domain.Enums.CapacityState), x.Rah_St),
Rah_LinesId = x.Rah_LinesId
}).OrderByDescending(o => new { o.Rah_CapacityId });
return result;
}
GetName couldn't be translated to T-SQL, Linq to Entities couldn't recognize it. You can modify the code as below:
var result = (from x in Data().AsEnumerable()
select new
{
Rah_CapacityId = x.Rah_CapacityId,
Rah_CapacityName = x.Rah_CapacityName,
Rah_St = Enum.GetName(typeof(Domain.Enums.CapacityState), x.Rah_St),
Rah_LinesId = x.Rah_LinesId
}).OrderByDescending(o => new { o.Rah_CapacityId });
With .ToList() after data is loaded, any further operation (such as select) is performed using Linq to Objects, on the data already in memory.
EDIT: Also your method's return type is IQueryable while your query is IOrderedEnumerable of anonymous type, so you should either change the method's type to System.Object or as a better solution create a class, send the values into the class's properties, and then return it.
You can't use this method in Linq-To-Entities because LINQ does not know how to translate Enum.GetName to sql. So execute it in memory with Linq-To-Objects by using AsEnumerable and after the query use AsQueryable to get the desired AsQueryable:
So either:
var result = Data()
.OrderBy(x=> x.CapacityId)
.AsEnumerable()
.Select(x => new
{
Rah_CapacityId = x.Rah_CapacityId,
Rah_CapacityName = x.Rah_CapacityName,
Rah_St = Enum.GetName(typeof(Domain.Enums.CapacityState), x.Rah_St),
Rah_LinesId = x.Rah_LinesId
})
.AsQueryable();
You should first use OrderBy before you use AsEnumerable to benefit from database sorting performance. The same applies to Where, always do this before AsEnumerable(or ToList).

Construct LINQ query using variables in asp.net WebAPI

I am trying to build a method in my asp.net WebAPI to grab data based on the arguments passed on the method. The method is used to perform a search on restaurant data. I have a variable called 'type' that determines the type of data search performed. The second variable 'keyword' is the keyword searched by the user. The WHERE condition in my LINQ query depends on the type and needs to be dynamic, so I have used a separate variable outside the LINQ query to define the condition. I have tried assigning this variable to my WHERE statement on the LINQ query but it doesn't seem to work. Can someone help with it please? I have been stuck on this for a few days now
public IQueryable<RestaurantView> GetRestaurantsForSearch(string keyword, int type, string location)
{
//
var condition = "";
if(type == 1)
{
condition = "x.RestaurantName.Contains(keyword)";
} else if(type == 2){
condition = "x.Cuisine.Equals(keyword)";
}
else {
condition = "x.Rating.Equals(keyword)";
}
var query = from x in db.Restaurants
join y in db.Cuisine on x.RestaurantCuisine equals y.CuisineID
where condition
select new RestaurantView
{
RestaurantID = x.RestaurantID,
RestaurantName = x.RestaurantName,
RestaurantCuisine = y.CuisineName,
RestaurantDecription = x.RestaurantDecription
};
return query;
}
Try this:
Predicate<Restaurant> pred;
if (type == 1) pred = x => x.RestaurantName.Contains(keyword);
else if (type == 2) pred = x => x.Cuisine.Equals(keyword);
else pred = x => x.Rating.Equals(keyword);
var query = from x in db.Restaurants
join y in db.Cuisine on x.RestaurantCuisine equals y.CuisineID
where pred(x)
select new RestaurantView
{
RestaurantID = x.RestaurantID,
RestaurantName = x.RestaurantName,
RestaurantCuisine = y.CuisineName,
RestaurantDecription = x.RestaurantDecription
};
return query;
You need to look a dynamic linq library i think then you can execute string statements inside your linq
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
or you can execute direct query
http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.executequery.aspx
If you are ok with dropping your comprehensive LINQ query in favour of the extension method syntax, it's pretty simple (I'm on a netbook without VS, so I apologize that this is untested but should give you the idea):
var query = db.Restaurants
.Include("Cuisine")
if(type == 1)
{
query= query.Where(x => x.RestaurantName.Contains(keyword));
}
else if(type == 2)
{
query = query.Where(x => x.Cuisine == keyword);
}
else {
query = query.Where(x => x.Rating == keyword);
}
This builds out your expression tree differently based on your logic checks, which will result in a different SQL query being generated based on the value of type.
I notice that in your join, Cuisine appears to be an Entity, but in your logic checks, you attempt to filter by comparing Cuisine to a string so I think there is some disconnect.
var query = from x in db.Restaurants
join y in db.Cuisine on x.RestaurantCuisine equals y.CuisineID
where condition
select new RestaurantView
{
RestaurantID = x.RestaurantID,
RestaurantName = x.RestaurantName,
RestaurantCuisine = y.CuisineName,
RestaurantDecription = x.RestaurantDecription
};
return query;
}
how to get the return query value in client side to assign for grid view binding

Getting around lack of 'Contains' in Linq To Entities

I have the following function (which is hosted in a WCF service, if that matters):
public List<IceVsRepositoryFile> GetRepositoryFilesByRepositoryId(int repId)
{
var entity = new IceVSEntities();
var files = from p in entity.Files where p.RepositoryId == repId select p.FileId;
List<long> iList = files.ToList();
var repFiles = from p in entity.RepositoryFiles where iList.Contains(p.FileId) select p;
if (!repFiles.Any())
return null;
var retFiles = repFiles.ToList().Select(z => new IceVsRepositoryFile
{
FileId = (int)z.FileId,
RollbackFileId = (int)z.RollbackFileId,
UserId = (int)z.UserId,
FileContents = z.FileContents,
ChangeDescription = z.ChangeDescription
}).ToList();
return retFiles;
}
When I run this function I am getting the following an error that says "LINQ to Entities does not recognize the method 'Boolean Contains(Int64)' method and this method cannot be translated into a store expression.
I understand why I am getting the error message. My question is, how can I rewrite my query to make this work as expected? My backend database, if it matters, if SqlLite 3. I am using .NET 3.5.
The contains you used is for List, it's not in IEnumerable so it can't be converted to corresponding sql query. Instead you can use Any, ... like:
iList.Any(x=>x == p.FileId) (or use related property)
Also instead of doing:
List<long> iList = files.ToList();
use files.Any... in your query to prevent from too many fetching from DB. Actually use IEnumerable functions instead of List functions.
I believe a join can do this:
public List<IceVsRepositoryFile> GetRepositoryFilesByRepositoryId(int repId)
{
var entity = new IceVSEntities();
var repFiles = from file in entity.Files where file.RepositoryId == repId join repFile in entity.RepositoryFiles on repFile.FileId equals file.FileId select repFile;
var retFiles = // as before
return retFiles;
}
Do you have a relationship between Files and RepositoryFiles? If so, it would be easier to do something like this:
var repFiles = from p in entity.RepositoryFiles where p.File.RepositoryId == repId select p;
This will avoid the problems with being unable to translate the query to SQL.

Categories

Resources