Error using EF6 DbFunctions.TruncateTime comparing DateTime - c#

I`m trying to retrieve some data from a data range using the following code:
var rotas = db.X.Where(r => r.DataDaExecucao != null)
.Where(r => System.Data.Entity.DbFunctions.TruncateTime(r.Date.Value) >= System.Data.Entity.DbFunctions.TruncateTime(startDateTime))
.Where(r => System.Data.Entity.DbFunctions.TruncateTime(r.Date.Value) < System.Data.Entity.DbFunctions.TruncateTime(endDateTime))
.Join(db.T, r => r.Id, t => t.X_Id.Value,
(r, t) => new
{
id = r.Id,
start = r.Date.Value.ToString("s"),
end = r.Date.Value.AddDays(1).ToString("s"),
title = t.Z.Name,
allday = false
}).ToList();
"Date" properties are Nullable< DateTime>.
I`m getting the following error message:
LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression.
Exception Details: System.NotSupportedException: LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression.
Also, I don`t have the System.Data.Entity.dll assembly referenced in my csproj.
Ideas?
Thank you, in advance.

You can change the anonymous type using SqlFunctions where it will also generate the sql query.
In your case you use ToString("s"), meaning you want to get the date part of second that can be replaced by SqlFunctions::DatePart. And Date::AddDays can be replaced by SqlFunctions::DateAdd.
new
{
id = r.Id,
start = SqlFunctions.DatePart("s", r.Date),
end = SqlFunctions.DatePart("s", SqlFunctions.DateAdd("d", 1, r.Date)),
title = t.Z.Name,
allday = false
}

DateTime.ToString() cannot be converted into a SQL statement by LINQ to Entities. e.g.
start = r.Date.Value.ToString("s")
The thing to do is call .ToList() to force the LINQ to Entities to execute its underlying SQL query. That way the remainder of the LINQ statement will use LINQ to Objects (in-memory query of a collection of objects).
In your case I would break the LINQ statement into 2 parts:
The first half which queries the DB with LINQ to Entities SQL generation, and calls .ToList() at the end
The second half which runs LINQ to Objects to do the in-memory part.

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();

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).

Linq To Entity giving error while populating dropdownlist in asp.net mvc 4?

I am facing issues while populating dropdownlist.
Using below code to populate IEnumerable
IEnumerable<SelectListItem> itemCollection = context.Countries.Select(item => new SelectListItem
{
Text = item.CountryName,
Value = item.CountryId
});
it gives error in Value = item.CountryId Cannot implicitly convert type int to string.
if I changes this to Value = Convert.ToString(item.CountryId) it give run time error
LINQ to Entities does not recognize the method 'System.String
ToString(Int32)' method, and this method cannot be translated into a
store expression.
I understand that the problem is Linq does not allow convert statement while executing. But the countrID is int in my database cannot be changed.
I know there are options to workaround this, but i need something concrete that will not make code messy?
If you call the AsEnumerable extension method, you will get your data and execute your query in memory. Otherwise, your query would be transalated to a dynamic sql query, which coulnd't be executed by your RDBMS due to the fact that there isn't any equivalent expression for ToString in SQL.
IEnumerable<SelectListItem> itemCollection =
context.Countries
.AsEnumerable()
.Select(item => new SelectListItem
{
Text = item.CountryName,
Value = item.CountryId.ToString()
});

LINQ to Entities does not recognize the method 'System.Linq.IQueryable`

I want to run this LINQ simple code to have record number in LINQ but result is beneath error
var model = _db2.Persons.Select(
(x, index) => new
{
rn = index + 1,
col1 = x.Id
}).ToList();
Error:
LINQ to Entities does not recognize the method
'System.Linq.IQueryable1[<>f__AnonymousType22
[System.Int32,System.Int32]] Select[Person,<>f__AnonymousType22](System.Linq.IQueryable1
[MvcApplication27.Models.Person], System.Linq.Expressions.Expression1[System.Func3
[MvcApplication27.Models.Person,System.Int32,<>f__AnonymousType2`2
[System.Int32,System.Int32]]])' method, and this method cannot be translated into a store
expression.
The problem is that LINQ to Entities doesn't understand how to convert that Select overload (the one that gives you the index) into a SQL query. You can fix this by first selecting the portion from the DB you need (to avoid selecting every column unnecessarily), then doing AsEnumerable() to take it as an IEnumerable<T> instead of an IQueryable<T>, and then doing the Select purely in C# (in short, IQueryable<T>s are converted to SQL, while IEnumerable<T>s are run in code).
var model = _db2.Persons.Select(x => x.Id).AsEnumerable().Select(
(id, index) => new
{
rn = index + 1,
col1 = id
}).ToList();
Note that the query as you have it appears to be unordered, so the id/index pairings can change each time you call this. If you expected consistency, you should order by something (e.g. _db2.Persons.OrderBy(...)).
Edit
Adding comment from Scott:
As a nice reference here is the list of all Linq statements built in
to the framework and a listing if it is compatible or not.
You could just select the Id and after it create your own anonymous object using linq to objects, for sample:
var model = _db2.Persons.Select(x => x.Id)
.ToList() // return int[]
.Select((id, index) => new
{
rn = index + 1,
col1 = id
}) // return anonymous[] (with rn and col1)
.AsEnumerable(); // get an IEnumerable (readonly collection)
Problably this is happen because Entity Framework does not support this kind of query using linq as linq could do in memory, so, in this case, you could select just you need (id in your case) and execute it, using ToList() method to concretize your query and after that you will have a list on memory, so, you can use linq to objects and use the supported method as you want.

How to use ToString() method to convert an integer to string inside LINQ

When I try to use ToString() inside the below LINQ Lambda expression, I get an exception saying "LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression."
query = query.Where(q => q.date.ToString().Contains(filtertext)
|| q.invoicenum.ToString().Contains(filtertext)
|| q.trans_type.ToString().Contains(filtertext)
|| q.charge.Contains(filtertext));
I am using Linq to entites. And the Database used is MySQL and not the SQL Server. Immediate help would be highly appreciated.
I resolved this issue by directly writing MySQl query inside C# as below -
string queryTemplate =
#"select inv.* from invoices as inv where userID = '123' and date like '%abc%'";
List<invoice> totalSearch =
context.ExecuteStoreQuery<invoice>(queryTemplate).ToList();
Harshal, the issue is the SqlFunctions.StringConvert is for MS SQL, not for MySQL. You can try convert the results to Enumerable and then query on it. Example:
using (DatabaseEntities db = new DatabaseEntities())
{
var list = from l in db.Customers.AsEnumerable()
orderby l.CompanyName
select new SelectListItem { Value = l.CustomerID.ToString(), Text = l.CompanyName };
return list.ToList();
}
Note the line:
l in db.Customers.AsEnumerable()
is converting the results to Enumerable, then you can use .toString() on it. You can adapt this to your needs.
In EF 4 you can use SqlFunctions.StringConvert

Categories

Resources