Method not supported in LINQ Store expression - c#

I am using LINQ to Entities for selecting data from SQL.
Here is my statement
var employee = from p in _context.employee
select p;
employee = employee.Where(p =>
Helper.RemoveSpecialCharacters(p.IdentificationNumber).
Equals(Helper.RemoveSpecialCharacters(search.IdentificationNumber)));
var Results = employee.ToList();
I am using RemoveSpecialCharacters method which I wrote to compare both sides of comparison without special characters.
Here I Get error, "RemoveSpecialCharacters" Method is not supported by Linq->Entity and is not a valid Store Expression.
I understand that it can't be translated as SQL. But how do I make such comparison using LINQ?
RemoveSpecialCharacters Method
public static string RemoveSpecialCharacters(string str)
{
char[] arr = str.Where(c => (char.IsLetterOrDigit(c))).ToArray();
str = new string(arr);
return str;
}
If methodname be translated to LINQ store then maybe how can I put this in linq so that sql understands it.

If you can express your RemoveSpecialCharacters in SQL, you could have a SQL view presenting your employees with a computed IdentificationNumberWithoutSpecialCharacters column, and then filter on it.
You could also reuse your C# implementation of the method by creating a .NET assembly for SQL Server.

The .ToList() finishes off your initial DB query, and gives you an
in-memory representation to work with and modify to your object.
var employee = from p in _context.employee
select p.ToList();
string searchIdent = Helper.RemoveSpecialCharacters(search.IdentificationNumber);
employee = employee.Where(p =>
Helper.RemoveSpecialCharacters(p.IdentificationNumber).
Equals(searchIdent));
var Results = employee;

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

Query not executing and not getting the reults

const string keyword = "manoj";
rsp.DataSource = company.GetCompanySearch(keyword);
rsp.DataBind();
using (var context = huntableEntities.GetEntitiesWithNoLock())
{
IEnumerable<Company> query = context.Companies.ToList();
if (!string.IsNullOrEmpty(keyword))
{
keyword = keyword.ToLower();
query = query.Where(u=>u.CompanyName.Contains(keyword)
|| u.EmailAdress.Contains(keyword)
||u.MasterCountry.Description.Contains(keyword)
||u.MasterIndustry.Description.Contains(keyword)
||u.CompanyDescription.Contains(keyword)
||u.CompanyHeading.Contains(keyword));
}
return query.ToList();
}
Query not getting the results. The database has 27 records with name manoj.
The inner exception is null for this
It should work as expected if you change the line IEnumerable<Company> query = ... to
var query = context.Companies;
This turns query into an IQueryable<Company>, of which the expression will be extended by the line query = query.Where(.... This will be done in a way that the Contains expressions will be translated into SQL (LIKE).
In your current code you fetch all Companies into memory and the Contains is executed by linq-to-objects. This is case-sensitive, the reason why I think you did not get any matches. The SQL is probably case-insensitive. That depends on the collation of your database.

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.

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