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.
Related
I use Linq to Sql and method syntax of Linq in my code to query from database with all tables. And I met an weird exception today, this is the first time error occurred since I started to use L2S.
There are two columns in database table.
And the column of "Status" is mapping to program with an enumeration type: 1(Free), 2(Loan).
。Database table schema as below.
。Define table class
private string Type;
private byte Status;
。Query code
string _qNote = string.Empty;
string _qStatus = string.Empty;
List<DefineTableClass> _List = _dbObj.Table.Select(_obj => _obj)
.Where(_obj =>
(string.IsNullOrWhiteSpace(_qNote) || _obj.Note == _qNote)
&& (string.IsNullOrWhiteSpace(_qStatus) || Convert.ToInt32(_obj.Status) == Convert.ToInt32(_qStatus))
).ToList();
The exception occurred at
Convert.ToInt32(_obj.Status) == Convert.ToInt32(_qStatus)
and I am wondering this line should be passed at
(string.IsNullOrWhiteSpace(_qStatus)
due to _qStatus is Empty and it should not to do the next check.
Improve your query by preparing parameters outside Queryable lambda:
string _qNote = string.Empty;
string _qStatus = string.Empty;
var query = _dbObj.Table.AsQueryable();
if (!string.IsNullOrWhiteSpace(_qNote))
query = query.Where(_obj => _obj.Note == _qNote);
if (!string.IsNullOrWhiteSpace(_qStatus))
{
var byteStatus = Convert.ToByte(_qStatus);
query = query.Where(_obj => _obj.Status == byteStatus);
}
var _List = query.ToList();
It should produce more effective SQL and may avoid unwanted conversions.
I found the similar situations with my question.
L2S will check ALL where conditions, so it must to do (string.IsNullOrWhiteSpace(_qStatus) no matter the front check we think it's should be passed cause it's true.
The better way to write L2S might less use casting in the syntax and like #SvyatoslavDanyliv said, preparing parameters outside Queryable lambda can prevent the weird logic question as mine at this time.
Reference:
Why isn't this short circuit is not working in linq to sql query?
Why isn't this short circuit in lambda working?
So I have this query on MSSQL where BANKS is a Table View
SELECT t.*
FROM [DB].[dbo].[BANKS] t
where t.BCODE = 'xxxxxx '; <--- with spaces
which above query has 1 result BCODE : "xxxxxx" <--- no space
on converting it to entity framework using ToList() or as IEnumerable(); e.g.
var _BANKS = dbcontext.BANKS.IEnumerable();
//var _BANKS = dbcontext.BANKS.ToList();
Just note that I have to put this on a Memory because I constantly refer to this table as reference.
On simple execution
string bankcode = "xxxxxx ".Trim();
var test = _BANKS.Where(q => q.BCODE == bankcode ).ToList(); // <--- would return me null
var test2 = from t in _BANKS where t.BCODE == "xxxxxx" select new t; <--- still null
but when I change the _BANKS as AsQueryable(); using the same code snippet above, it would give the desired result the same on the native query (see first SQL snippet).
I'm avoiding the .AsQueryable() because it will give me a runtime error specifically
"The specified LINQ expression contains references to queries that are associated with different contexts."
because I'm using it to constantly refer in a different DBContext's.
The reason why in case of a simple SQL statement, you got one result is pretty obvious for me:
it is that in the database, you have a record which contains spaces, i.e. 'xxxxxx '.
Now why it is not working when using the below code?:
string bankcode = "xxxxx ".Trim();
var test = _BANKS.Where(q => q.BCODE == bankcode ).ToList(); // <--- would return me null
var test2 = from t in _BANKS where t.BCODE == "xxxxxx" select new t; <--- still null
Because you are trimming the bankcode which will lead to converting "xxxxx " to "xxxxx" but in the database, you have an actual record matching this "xxxxx ". That's why it will return null which means it will not find matching records.
To overcome this issue use LINQ to SQL Contains() method:
string bankcode = "xxxxx ".Trim();
var test = _BANKS.Where(q => q.BCODE.Contains(bankcode)).ToList();
The issue was not in the .ToList() or the .IEnumerable, but rather it is related to a memory leak when you are trying to save the data in the Memory from a Table view.
Workaround
var _BANKS = (from banks in dbcontext.BANKS
select new {
banks.BCODE,
// ... so on.
}).ToList();
re-selecting the LINQ from storing into your Memory weirdly corrects the inconsistency.
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;
I have a sql server procedure I am accessing with Linq to Sql. When I execute the query I am getting the error 'The Query Results cannot be enumerated more than once'. The parameter is entered in the txtName text box and the results are displayed in the lstName listview.
public void GetSearchString()
{
Data.Database.FRCDatabaseDatacontext context =
new Data.Database.FRCDatabaseDatacontext();
var result = context.GetSearchProcedure(txtName.Text);
foreach (GetSearchProcedureResult search in result)
if ( search.UserGuid ==
Workspace.Instance.ActiveUser.CurrentUserActiveDirectoryGuid)
{
lstName.ItemsSource = result.ToList();
}
}
This method will return every result, but I want to return the results where the guids match.
Thanks!
Data.Database.FRCDatabaseDatacontext context =
new Data.Database.FRCDatabaseDatacontext();
var result = context.GetSearchProcedure(txtName.Text);
lstName.ItemsSource = result.ToList();
You are trying to enumerate the data more than once - once in the foreach and then again with the .ToList() for each matching UserGuid, which is causing the error.
Perhaps this LINQ select statement will help:
public void GetSearchString()
{
Data.Database.FRCDatabaseDatacontext context = new Data.Database.FRCDatabaseDatacontext();
lstName.ItemsSource = (from s in context.GetSearchProcedure(txtName.Text)
where s.UserGuid == Workspace.Instance.ActiveUser.CurrentUserActiveDirectoryGuid
select s).ToList();
}
public void GetSearchString()
{
var context = new Data.Database.FRCDatabaseDatacontext();
var result = context.GetSearchProcedure(txtName.Text);
var itemSource = result.ToList();
foreach (GetSearchProcedureResult search in itemSource)
if (search.UserGuid == Workspace.Instance.ActiveUser.CurrentUserActiveDirectoryGuid)
{
lstName.ItemsSource = itemSource;
}
}
Anyway, It will be better to pass the parameter to procedure instead recalculating it in the code
Calling .ToList on an IQueryable causes it to be materialized (i.e. the query is passed on to the back-end provider). Obviously, this is something that you'd probably prefer to only do once, as it's likely to be an expensive operation. This is what the error is trying to tell you.
If you only call .ToList once and store the result, the problem should go away.
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