LINQ is converting string to special characters - c#

I am using this query to get data from database.
string nfc = "53f8372c";
var temp = db.tempTable.AsNoTracking().Where(
x =>
x.uid.Equals(nfc, StringComparison.CurrentCultureIgnoreCase)
&& x.ENDED == null
&& x.STATUS.Equals(Constants.ACTIVE)
);
The sql that is generated from this query is:
{SELECT
"Extent1"."ID" AS "ID",
"Extent1"."uid" AS "uid",
"Extent1"."ENDED" AS "ENDED",
"Extent1"."STATUS" AS "STATUS",
FROM "tempTable" "Extent1"
WHERE (("Extent1"."uid" = :p__linq__0) AND ("Extent1"."ENDED" IS NULL) AND ('Active' = "Extent1"."STATUS"))}
Why does it convert 53f8372c to :p__linq__0?

That's just parameterizing the SQL. If you look at the parameters passed to the query, you'll see that :p__linq__0 has a value of 53f8372c.
This parameterization is helpful, as the server can cache the query plan and reuse it for the same query using different parameter values.

Related

LINQ to Entities does not recognize the method Urls.MeaningfulURL, and this method cannot be translated into a store expression

This question is specific to taking in a formatted url value and comparing to an unformatted database value.
I have a url /companies/my-company/
The company's name is stored in the database field as "My Company" - note: no hyphen, space and uppercase.
It could be stored in an even more complex format like "John's Company >>" because the user has the ability to input this in the CMS.
So how do I compare my-company to My Company in LINQ to Entites?
var type = Context.Set<Domain.Content.Organisation>()
.AsNoTracking()
.Select(x => new DataContracts.Content.Organisation
{
Id = x.Id
,Name = x.Name
,OrganisationTypeId = x.OrganisationTypeId
,OrganisationTypeName = (x.OrganisationType != null) ? x.OrganisationType.Name : string.Empty
,Categories = x.Categories.Select(i => i.Id)
,IsCustomer = x.IsCustomer
,CountryId = x.CountryId
,CountryName = (x.Country != null) ? x.Country.Name : string.Empty,
SeoName = x.SeoName,
Description = x.Description,
Website = x.Website
})
.FirstOrDefault(x => x.Id == id || Urls.MeaningfulURL(x.SeoName.ToLower(), null) == seoName.ToLower());
The problem here is:
Urls.MeaningfulURL(x.SeoName.ToLower(), null) == seoName.ToLower()
It generates an error:
LINQ to Entities does not recognize the method Urls.MeaningfulURL method, and this method cannot be translated into a store expression.
I understand what it means, but cannot figure out a way around it.
Urls.MeaningfulURL is a method that does a lot of string replacements to create the url format 'my-company'.
How can I format column x.SeoName at query time correctly so it matches my url input ?
Thanks
EF cann't translate Urls.MeaningfulURL to SQL. There are so many options to resolve it:
1. Load data first:
var type = Context.Set<Domain.Content.Organisation>()
.AsNoTracking()
.Select(your select)
.ToList()
.FirstOrDefault(x => x.Id == id || Urls.MeaningfulURL(x.SeoName.ToLower(), null) == seoName.ToLower());
it's simplest but it produces perfomance problems cause all Organisation will be loaded from db into memory.
2. Rewrite your logic.
You cann't apply custom method to x.SeoName so just don't do that. Try to rewrite your query to:
var type = Context.Set<Domain.Content.Organisation>()
.AsNoTracking()
.Select(your select)
.FirstOrDefault(x => x.Id == id || computedString.Contains(x.SeoName));
And yes, you can use Contains, at least for SQL Server provider.
3. Move your logic to SQL:
If SQL Server is used, you can try computed column, view, and even CLR code on SQL Server etc.
4. Store the computed value in db:
Sometimes it is better to store Urls.MeaningfulURL(x.SeoName.ToLower(), null) value instead or together with x.SeoName and use this stored value in queries. Also it becomes possible to add an index on this field.

Convert string to long type and use in a linq query within asp.net MVC

Is it possible within Linq in C#, to convert a string field in a database, to a long type - and use it in the query?
Here, tme is a unix time (long) - but the field in the database, targetdate - is a string.
I've tried:
var qbt = db.Calls
.Where(x => x.team == id && long.Parse(x.targetdate) <= tme);
However I get the message: LINQ to Entities does not recognize the method 'Int64 Parse(System.String)' method, and this method cannot be translated into a store expression.
I know you can convert before the linq query, but is there any way of using it WITHIN the linq query?
Thanks for any help,
Mark
try
var qbt = db.Calls.ToList()
.Where(x => x.team == id && long.Parse(x.targetdate) <= tme);
if you have many records you can limit them by team first and then call ToList like below
var qbt = db.Calls.Where(x => x.team == id).ToList()
.Where(i=>long.Parse(i.targetdate) <= tme);
Or You can use AsEnumerable
var qbt = db.Calls.AsEnumerable()
.Where(x => x.team == id && long.Parse(x.targetdate) <= tme);
This is to do with the way the Linq is translated into the backing query language, it might be easier to do a string comparison in this case, using tme.ToString(). If you pull the full collection down first, you could query like this but that means what it says: pulling down the full unfiltered (or at least less filtered) set.
You have to either change the database table to not store a string (you could create a computed column that converts it to a long or create a view if you cannot modify the existing table) or compare the value as string. The reason is that Entity Framework LINQ provider does not understand long.Parse and there is no method in SqlFunctions class for this purpose.
var stringTme = tme.ToString(CultureInfo.InvariantCulture);
var qbt = db.Calls
.Where(x => x.team == id && ((x.targetdate.Length < stringTme.Length)
|| (x.targetdate.Length == stringTme.Length && x.targetdate <= stringTme)));
You have to either change the database table to not store a string or compare the value as string. The reason is that Entity Framework LINQ provider does not understand long.Parse and there is no method in SqlFunctions class for this purpose.please use long.Parse()

Linq query translation to SQL messes up null parameter values

Here's a simple LINQ query:
var objs = db.Objects.Where(o => o.Field1 == val);
This translates to SQL query:
select * from [Object] where Field1 = #p1
Trouble is, the value of val can also legitimately be null. And SQL doesn't like comparing nulls; it insists on the syntax ... where Field1 is null.
Is there any way of doing this neatly, short of using a ?? / isnull operation?
This, again, is an EF weakness in LINQ support. Good old LINQ to SQL translated this properly depending on the runtime value of val.
I suggest you go with this:
var objs = db.Objects.Where(
o => (o.Field1 == val) || (o.Field1 == null && val == null));
If EF translates this litterally, the SQL Server query optimizer will actually pick up this pattern and optimize it to an "equals-with-nulls" check. You can even seek indexes using this code pattern, it just works. In the query plans this shows up as IS in contrast to EQ.
How about .HasValue?
var objs = db.Objects.Where(o => !o.Field1.HasValue && o.Field1 == val);

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.

Handling null values in where clause using LINQ-to-SQL

The LINQ-to-SQL query in Visual Studio generates an SQL query with errors. In LINQPad, the same LINQ query using the same database (or DataContext) runs just fine.
LINQ Query
var accesDomaines = from t in db.Access
where t.IdUser == access.IdUtilisateur
where t.IdDomain != null
where t.IdRole == access.IdRole
where t.IdPlace == access.IdPlace
select t;
Here's a small part of generated SQL where the error occurs:
WHERE (...) AND ([t3].[IdRole] = ) AND (...)
After the equals in where clause, there's literally nothing ! In the SQL query of LINQPad we see the good where clause:
WHERE (...) AND ([t3].[IdRole] IS NULL) AND (...)
When I compare the two generated SQL queries from VS and LINQPad, line by line, this is the same thing. Except LINQPad is using params and also the missing right part of equal in where clause of Visual Studio, as shown before.
Note 1
In the LINQ query, I tried with this syntax in where clauses:
where t.IdRole.Equals(acces.IdRole.Value)
But also generates a bad result. I even tried something like this before the LINQ query:
if (!acces.IdRole.HasValue) { acces.IdRole = null; }
Note 2
Properties are nullable integers. I do want null in query if property is null. Obviously, I want the value of property if there's a value.
Note 3
I have tried the proposition made in this question: Linq where column == (null reference) not the same as column == null
...with no success.
Any explanation of two similar LINQ queries, but generating a good and a bad SQL query? Any suggestion to solve this problem?
Thank you!
try this:
where object.Equals(t.IdRole, access.IdRole)
Use
object.Equals()
.Net would take care of generating correct sql for null condition.
Example:
Say you have a street table with columns like Suffix and Prefix. Then following linq query doesn't work:
string suffix = "ST";
string prefix = null;
var map = from s in Streets
where s.Suffix==suffix || s.Prefix==prefix
select s;
It would generate following sql:
SELECT [t0].[StreetId], [t0].[Prefix], [t0].[Suffix]
FROM [Street] AS [t0]
WHERE ([t0].[Suffix] = #p0) AND ([t0].[Prefix] = #p1)
we can clearly see it will not return any result.
Using object.Equals():
string suffix = "ST";
string prefix = null;
var map = from s in Streets
where object.Equals(s.Suffix, suffix) && object.Equals(s.Prefix,prefix)
select s;
would generate sql:
SELECT [t0].[StreetId], [t0].[Prefix], [t0].[Suffix]
FROM [Street] AS [t0]
WHERE ([t0].[Suffix] IS NOT NULL) AND ([t0].[Suffix] = #p0)
AND ([t0].[Prefix] IS NULL)
Which is correct one.
(Little late, but wanted to expand the answer for the benefit of others)
Have you tried verifying whether your properties had values with the HasValues property provided by the Nullables?
where t.IdRole == access.IdRole.HasValues ? access.IdRole.Value : null
Perhaps this could work. I haven't used LINQ-to-SQL really.
This example worked for me:
var aff3 = from a in context.Affiliates
where ((name == null && a.CompanyName == null) || (a.CompanyName == name))
select a.ID;

Categories

Resources