I am trying to return rows based on a search term that may include a space.
The code below is is generating the following error. I cannot figure out what I'm doing wrong, any suggestions?
Local sequence cannot be used in LINQ to SQL implementations of query
operators except the Contains operator.
var searchTerms = term.Split(' ').ToList();
var surveys = (from s in dc.BasicNeedsSurveys where s.Hidden ==
false orderby s.CreatedOn descending select s)
.Where(x => searchTerms.Any(y => y.Contains(x.FirstName))
|| searchTerms.Any(y => y.Contains(x.LastName))
|| searchTerms.Any(y => y.Contains(x.FEMANumber)));
according to the error message you are using linq to sql (or EF). linq to sql generate SQL query behind the scene, and you cant use a local var such as searchTerms inside an sql query. if i understand it correctly and dc.BasicNeedsSurveys is actually a data base entity (like in entity framework for example) your solution will be to first execute the sql query and then run the test if substring of search terms contains the search result. ToList is one function that can do that.
var searchTerms = term.Split(' ').ToList();
var surveys = (from s in dc.BasicNeedsSurveys where s.Hidden ==
false orderby s.CreatedOn descending select s)
.ToList()
.Where(x => searchTerms.Any(y => y.Contains(x.FirstName))
|| searchTerms.Any(y => y.Contains(x.LastName))
|| searchTerms.Any(y => y.Contains(x.FEMANumber)));
of course, there might be better ways to do that with better performance since here you are filtering the results only after you read all of them from the hard drive, but there is really not enough information in the question for that
Related
I'm querying the Azure Cosmos DB and need to apply a filter based on an array of Search terms.
Something like below:
searchTerms = searchTerms.Where(s => s != null).Select(f => f.ToLower()).ToArray();
query = query.Where(uci => searchTerms.Any(f => uci.User.FirstName.ToLower().Contains(f))
|| searchTerms.Any(f => uci.User.LastName.ToLower().Contains(f))
|| searchTerms.Any(f => uci.User.Company.Name.ToLower().Contains(f)));
However the query fails with an error "Input is not of type IDocumentQuery"
So, "Any" is not supported by Microsoft.Azure.Cosmos.
The alternative was to use the sql query instead of using linq. SQL has 2 options "Array_contains" or "Contains" but that doesn't work because
Array_contains does a "=" check on the array elements rather than substring check
eg. SELECT ARRAY_CONTAINS(["apples", "strawberries", "bananas"], "apples") AS b1
Contains works on a single string
eg. SELECT CONTAINS("abc", "ab") AS c1
cosmos array_contains
This link speaks about the "like" keyword, however that also works on a single string.
The closest solution that I could come up with is below
searchTerms = searchTerms.Where(s => s != null).Select(f => f.ToLower()).ToArray();
foreach (string term in searchTerms) {
query = query.Where(uci => uci.User.FirstName.ToLower().Contains(term)
|| uci.User.LastName.ToLower().Contains(term)
|| uci.User.Company.Name.ToLower().Contains(term));
}
This will add a "where" clause for each search term which is more of a hack than a solution.
Has anyone run across such situation? Any optimal suggestions?
I have a simple scenario.I want to list out all the employees except the logged in user.
Similar SQL Condition is
select * from employee where id not in(_loggedUserId)
How can I acheive the above using LINQ.I have tried the following query but not getting the desired list
int _loggedUserId = Convert.ToInt32(Session["LoggedUserId"]);
List<int> _empIds = _cmn.GetEmployeeCenterWise(_loggedUserId)
.Select(e => e.Id)
.Except(_loggedUserId)
.ToList();
Except expects argument of type IEnumerable<T>, not T, so it should be something like
_empIds = _cmn.GetEmployeeCenterWise(_loggedUserId)
.Select(e => e.Id)
.Except(new[] {_loggedUserId})
.ToList();
Also note, this is really redundant in the case when exclusion list contains only one item and can be replaces with something like .Where(x => x != _loggedUserId)
Why not use a very simple Where condition?
_empIds = _cmn.GetEmployeeCenterWise(_loggedUserId).Where(e=>e.Id != _loggedUserId).ToList();
The title of your question is how to perform a not in query against a database using LINQ. However, as others have pointed out your specific problem is better solved by a using users.Where(user => user.Id != loggedInUserId).
But there is still an answer on how to perform a query against a database using LINQ that results in NOT IN SQL being generated:
var userIdsToFilter = new[] { ... };
var filteredUsers = users.Where(user => !userIdsToFilter.Contains(user.Id));
That should generate the desired SQL using either Entity Framework or LINQ to SQL.
Entity Framework also allows you to use Except but then you will have to project the sequence to ID's before filtering them and if you need to original rows you need to fetch them again from the filtered sequence of ID's. So my advice is use Where with a Contains in the predicate.
Use LINQ without filtering. This will make your query execute much faster:
List<int> _empIds = _cmn.GetEmployeeCenterWise(_loggedUserId)
.Select(e => e.Id).ToList();
Now use List.Remove() to remove the logged-in user.
_empIds.Remove(_loggedUserId);
My application is running under ASP.NET 4.0, which uses BLToolkti as ORM tool.
I have some queryable expression:
var q = db.GetTable<T>()
.Where(tb=>tb.TeamId==MyTeamId && tb.Season==MySeasonId)
.OrderByDescending(tb=>tb.Id)
.Take(20)
.Reverse()
Attempt to convert q.ToList() causes the following error:
Sequence 'Table(TeamBudget).Where(tb => ((tb.TeamId ==
value(VfmElita.DataLogicLayer.Teams.Team+TeamBudget+<>c__DisplayClass78).teamId)
AndAlso (tb.Season ==
value(VfmElita.DataLogicLayer.Teams.Team+TeamBudget+<>c__DisplayClass78).season))).OrderByDescending(tb
=> Convert(tb.Id)).Take(20).Reverse()' cannot be converted to SQL.
If I remove ".Reverse()" from the queryable object everything works fine.
What is the reason why queryable object with .Reverse() cannot be converted into SQL? Is that BLToolkit limitation? Is there any solution workaround for that?
Thank you!
It's pretty clear what the other LINQ methods convert to (where, order by, top(20)), but what would Reverse() convert to? I can't think of an SQL statement I've seen that mimics that behavior, and when you're querying the database your LINQ statement must ultimately resolve to valid SQL.
This may not be what you're going for, but one option would be to execute the query first using ToList(), then apply Reverse():
var q = db.GetTable<T>()
.Where(tb => tb.TeamId == MyTeamId && tb.Season == MySeasonId)
.OrderByDescending(tb => tb.Id)
.Take(20)
.ToList()
.Reverse();
Alternatively, you could get the count and skip that many records first, although this could be inaccurate if the number of records change between calls. Plus it's two queries instead of just one.
var totalRecords = db.GetTable<T>()
.Count(tb => tb.TeamId == MyTeamId && tb.Season == MySeasonId);
var q = db.GetTable<T>()
.Where(tb => tb.TeamId == MyTeamId && tb.Season == MySeasonId)
.Order(tb => tb.Id)
.Skip(totalRecords)
.Take(20);
I got a product table and want to get datas sort by alphabetical. But when i write this query they are still coming by id. I check a lot of page in google but cant find any source.
var product = Db.tablename
.Where(s => s.colum == DropDownList2.SelectedValue)
.OrderBy(s=> s.Name);
This query
var product = Db.tablename
.Where(s => s.colum == DropDownList2.SelectedValue)
.OrderBy(s=> s.Name);
will not be executed until it is asked to. So you have to change it to the following one:
var product = Db.tablename
.Where(s => s.colum == DropDownList2.SelectedValue)
.OrderBy(s=> s.Name).ToList();
The reason why that happens is that actually you just have declared a query. I mean you haven't executed it. That's the nature of LINQ queries, which in technical terms is called deffered execution. On the other hand if you call the ToList() method at the end of your query, you will trigger the immediate execution of this query and it's result will be a List of the same type with s.Name.
You must use ToList to execute the sort.
var product = Db.tablename
.Where(s => s.colum == DropDownList2.SelectedValue)
.OrderBy(s=> s.Name).ToList();
The order by does nothing, just executes the query, the ToList will do the sort for the original query.
I am using LINQ to create a list. But I want to use a function at the end to generate the object iself, something LINQ complains about
LINQ to Entities does not recognize the method 'WashroomStatusItem GetWashroomStatusForItem(WashroomStatus)' method, and this method cannot be translated into a store expression.
What am I doing wrong?
var query = (from c in context.WashroomStatus
where c.WashroomId == GroupItem.WashroomID
select GetWashroomStatusForItem(c));
private WashroomStatusItem GetWashroomStatusForItem(WashroomStatus item)
{
WashroomStatusItem temp = new WashroomMonitorWCF.WashroomStatusItem();
//do stuff with it
return temp;
}
The problem is that the SQL conversion can't convert your method into SQL. You should use AsEnumerable() to "switch" from the out-of-process provider to LINQ to Objects. For example:
var query = context.WashroomStatus
.Where(c => c.WashroomId == GroupItem.WashroomID)
.AsEnumerable()
.Select(c => GetWashroomStatusForItem(c));
Note that if GetWashroomStatusForItem only uses some properties, you may want to project to those separately first, to reduce the amount of information fetched from the server:
var query = context.WashroomStatus
.Where(c => c.WashroomId == GroupItem.WashroomID)
.Select(c => new { c.Location, c.Date };
.AsEnumerable()
.Select(p => GetWashroomStatusForItem(p.Location, p.Date));
Jon Skeet's answer is correct, but I'd add that depending on the nature of GetWashroomStatusForItem(), it should probably either be broken down into LINQ statements and added into the query itself, or it should be executed after the query has returned.
So, lets say GetWashroomStatusForItem() looks something like this: note that this is extremely oversimplified.
public static WashroomStatus GetWashroomStatusForItem(Item c)
{
return c.WashroomStatus;
}
it should just be added to the LINQ query like this:
var query = (from c in context.WashroomStatus
where c.WashroomId == GroupItem.WashroomID
select c.WashroomStatus);
But if it relies heavily on stuff not in the db, I'd just end the Linq statement before you get the WashroomStatus, and then call GetWashroomStatusForItem() on the results. It's not gonna a performance difference since Linq uses lazy evaluation, and you generally want to keep db operations separate from "programmatic" ones.