This question already has answers here:
How to make LINQ execute a (SQL) LIKE range search
(3 answers)
Closed 5 years ago.
I try to do a request to my database and I want to use something like the "LIKE" operator in SQL to resolve this pattern: %{%}%
Using the "SQL-friendly" syntax.
Currently my request looks like:
var routelist = (from dbHost in db.Hosts
where dbHost.Host == host
join dbRoute in db.Route on dbHost.HostsId equals dbRoute.HostId
select dbRoute).ToList();
If someone know how to do, can he tells it to me ? Thanks
EDIT :
I want to do something like it :
var routelist = (from dbHost in db.Hosts
where dbHost.Host == host
join dbRoute in db.Route on dbHost.HostsId equals dbRoute.HostId
where dbRoute.alias like "%{%}%"
select dbRoute).ToList();
Entity Framework Core 2.0 has now available EF.Functions property that includes EF.Functions.Like().
https://blogs.msdn.microsoft.com/dotnet/2017/08/14/announcing-entity-framework-core-2-0/
Example:
var customers =
from c in context.Customers
where EF.Functions.Like(c.Name, "a%");
select c;
When I need to perform such LIKE queries with entity framework (and this happens very rarely, because such like queries usually cannot use any index and so perform full table scan and are quite slow on big tables), I use PATINDEX, like this:
var routelist = (from dbHost in db.Hosts
where dbHost.Host == host
join dbRoute in db.Route on dbHost.HostsId equals dbRoute.HostId
where SqlFunctions.PatIndex("%{%}%",dbRoute.alias) > 0
select dbRoute).ToList();
PATINDEX function in sql server is like LIKE, but returns the position of the first match.
If you want to perform LIKE query in a form of "%something%", you can use Contains("something"). If it has the form of "%something" - use StartsWith("something"). If it has the form of "something%" - use EndsWith("something").
Related
I am trying to write the following query using SQLKata for SQLServer:
SELECT Company FROM Table1 INNER JOIN Table2 ON LEFT(Table1.[Company], 5) = LEFT(Table2.accountName, 5)
I have tried the following:
var db = new QueryFactory(connection, compiler);
var query = db.Query("Table1")
.Join("Table2", "LEFT([Table1].[Company],5)", "LEFT([Table2].[accountName],5)")
.Select("Company").Get();
But the fails with the error 'The multi-part identifier could not be bound'.
It appears there is no JoinRaw that I can use in sqlKata either. Does anyone know if there is a way i can create a Left string function in sql kata and use in queries like the one above?
The issue here is that Sqlkata expect column names as string inside the Join method arguments, without any wrapper or functions, the reason is to prevent SQL injection, so expressions are not allowed here.
for such cases you can use the FromRaw method (See https://sqlkata.com/docs/from#from-a-raw-expression).
db.Query().FromRaw("[Table1] JOIN [Table2] LEFT([Table1].[Company],5) ON LEFT([Table2].[AccountName],5)")
In the coming version you can inject RawExpression for such cases but this is not officially released yet.
db.Query("Table1").Join(
"Table2",
Raw("Left([Table1].[Company], 5)"),
Raw("Left([Table2].[AccountName], 5)")
)
In a side note, performing a join based on an evaluated expression is not recommended and may lead to performance issues.
This question already has an answer here:
Why does the Contains() operator degrade Entity Framework' Linq queries?
(1 answer)
Closed 9 years ago.
I was looking for some tips to improve my entity framework query performance and came accross this useful article.
The author of this article mentioned following:
08 Avoid using Contains
In LINQ, we use contains method for checking existence. It is converted to "WHERE IN" in SQL which cause performance degrades.
Which faster alternatives are remaining for me?
Contains is perfectly valid for the scenarios you WANT WHERE IN
EG:
var q = from p in products where new[]{1,50,77}.Contains(p.productId) select p;
gets (essentially) converted to
SELECT * FROM products WHERE ProductId IN (1,50,77)
However if you are checking for existence I would advice you to use .Any() , which gets converted to EXISTS -
EG
var q = from p in products
where p.productsLinkGroups.Any(x => x.GroupID == 5)
select p
Gets (more or less) coverted to:
SELECT * FROM products p
WHERE EXISTS(
SELECT NULL FROM productsLinkGroups plg
WHERE plg.GroupId = 5 AND plg.ProductId = p.ProductId
)
It is very context dependent, what you should be looking at is not avoiding .Contains() but rather how do you avoid WHERE xx IN yy in SQL. Could you do a join instead? Is it possible to specify an interval rather than discrete values?
A perfect example is presented here: Avoid SQL WHERE NOT IN Clause
Where it was possible to avoid it by using a join.
I would say that WHERE xx IN yy is usually just a half a solution, often what you really want is something else and you only get halfway there instead of going there directly, like in the case of a join.
Hi all I am having a sql query which I would like to execute the same using entity framework and bind it to gridview can some one help me. This is my query
SELECT Technology,[Description], Technologies.TechID, COUNT(*) AS 'num_employees'
FROM Technologies
LEFT JOIN Questions
ON Questions.TechID = Technologies.TechID
GROUP BY Technologies.TechID, Technology,[Description]
How can I convert the same to get the results using EF
Personally, I would make this a stored procedure instead, and import it into EF. Then you would just call it in your code and databind the result to your grid.
This way the joining, grouping, etc all happens server side instead of client side. Otherwise, you'd be sending a lot more information than necessary to the client. Plus, the server can theoretically do these operations faster than a client's.
Try this, i didn't have the time to test it both for logic and syntax. You need something similar.
var q = from a in context.Technologies
join b in context.Questions
on a.TechID equal b.TechID into j1
from j2 in j1.DefaultIfEmpty()
group j2 by new { a.TechID, b.Technology, b.Description into grouped
select new { Tecnology = grouped.Technology, Description = grouped.Description, Count = grouped.Count() }
First of all I'm sorry because this is the second time that I write this question but before was bad explained and now is close.
I'm doing a linq query for a search page for a CRM data base, and wrtiting a normal query like below is not working, I'm getting the exception:
[System.ServiceModel.FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>] = {"'Contact' entity doesn't contain attribute with Name = 'title'."}
For a join query, that in the clause Where was something like r.Name == "Me" && j.LastName == "He" I had to did the query with two Where clauses, because I was getting the same exception as above, saying that table 'r' doesn't have 'LastName' attributte.
var cms = from i in aux_pr
join cal in Contact on i.aux_CallerRequestorID.Id equals cal.ContactId.Value
join sub in Subject on i.aux_ClassificationID.Id equals sub.SubjectId
where cal.FullName.Contains(searchTerm) ||
sub.Title.Contains(searchTerm)
In this case, how can I do this query. Thanks in advance!
I want to comment what have I learned and the solution that I have found to my problem hoping could help some one. There are some limitations in CRM LINQ, as explained here
The first that I found, having an entity reference like this:
CrmEntityReference Caller
{
Guid ID;
string name;
}
I can select Caller.name but I CAN'T have Caller.name in the where clause. Solution for this -> Join the table
The second limitation, is when we have joins in the query, we can have different tables in the where if they are an AND predicate, we have to write two clauses where like this:
where cal.FullName.Contains(searchTerm)
where sub.Title.Contains(searchTerm)
But the problem comes when instead of an AND we need use an OR predicate, the only solution we have is do two queries and after do an Union of these queries.
I have four queries for a call that could be done just with one, now in developing stage performance is good due to the amount of records, but we'll see in testing stage how this work.
try to create two different filters..
var cms = from i in aux_pr
join cal in Contact on i.aux_CallerRequestorID.Id equals cal.ContactId.Value
join sub in Subject on i.aux_ClassificationID.Id equals sub.SubjectId
where cal.FullName.Contains(searchTerm) ||
where sub.Title.Contains(searchTerm)
Scenario: I have a table of User Profiles and a table of Colleagues. The colleagues table has a record for ever other user that a User Profile is following. In this query, I am grabbing all of the people who are following the current logged in user (getting their Record IDs from the Colleagues table and joining the User Profile table to get their details). Then, I am joining the Colleagues table again to see if the logged in user is following that user back.
Issue: It is my understanding that the best way to do a LEFT JOIN (in looking for the colleague record where the user is following the colleague back) is to add "DefaultIfEmpty()" to that join. When I add .DefaultIFEmpty() to that join, I get the following error message:
System.NotSupportedException: LINQ to Entities does not recognize the method 'System.Collections.Generic.IEnumerable'
If I remove the ".DefaultIFEmpty()" from that join, it works. However, it runs it as a regular JOIN, leaving out records where the user is not following the colleague back.
Code: Here is the code I am using:
var results = (from a1 in db.Colleague
join b1 in db.UserProfile on new {ColleagueId = a1.ColleagueId} equals
new {ColleagueId = b1.RecordId}
join d1 in db.UserProfile on new {RecordId = a1.OwnerId} equals
new {RecordId = d1.RecordId}
join c1 in db.Colleague
on new {OwnerId = b1.RecordId, Ignored = false, ColleagueId = a1.OwnerId}
equals new {c1.OwnerId, c1.Ignored, c1.ColleagueId} into c1Join
from c1 in c1Join.DefaultIfEmpty() // This is the .DefaultIfEmpty() breaking the query
where
b1.AccountName == userName &&
a1.Ignored == false
orderby
b1.LastName
select new
{
RecordId = (System.Int64?) d1.RecordId,
d1.AccountName,
d1.PreferredName,
d1.FirstName,
d1.LastName,
d1.PictureUrl,
d1.PublicUrl,
IsFollowing = c1.OwnerId < 1 ? 0 : 1
});
foreach (var result in results) // This is what throws the error
{
// Do stuff
}
Any ideas?
The SQL Provider for Entity Framework in version 3.5 of the .NET framework does not support DefaultIfEmpty(). Sorry, but could not find a better reference than this article: http://smehrozalam.wordpress.com/2009/06/10/c-left-outer-joins-with-linq/
You might want to try straight LINQ-to-SQL rather than ADO.NET Entity Framework. I believe that it works in LINQ-to-SQL. I've verified in the past that left joins work in 3.5 via LinqPad.
DefaultIfEmpty is supported only in EFv4+. First version of EF doesn't support DefaultInEmpty.
It looks like you need to create a default value to pass into DefaultIfEmpty(), since DefaultIsEmpty() takes a parameter.
DefaultIfEmpty() on MSDN