Linq query from datasource with where ... like '%%' or ... like '%%' - c#

I'm trying to select all the fields from a db that contains any of the string contained in a list (that could be populated from user).
Is very easy for me to do by pure SQL with a sentence like
WHERE myfield LIKE '%nam%' OR myfield LIKE '%cod%' OR myfield LIKE '%big%'
but I need to do it with C# and Linq. I searched several solutions, some that recommend me to use .Any or .Contains but I didn't get it how to apply to my case :-(
This is the most close result I can achieve:
var query = DataSource.Docs();
...
IList<string> nameFilter = new List<string>() {"nam", "cod", "big"};
query = query.Where(x => x.NomeFile.Contains(nameFilter.FirstOrDefault()));
anyway with this silly code I filter just the elements are containing the first element of my list (the FirstOrDefault let ignore all the others)
Can anybody help me to find the right way?

You're looking for:
query.Where(x => nameFilter.Any(s => x.NomeFile.Contains(s)));

Have you tried this?
query = query.Where(x => nameFilter.Any(n => x.NomeFile.Contains(n)));
or
query = query.Where(x => nameFilter.Any(n => x.NomeFile.IndexOf(n) >= 0));

Related

NOT IN Condition in Linq

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

EF: LINQ - orderby using child collection with condition - ArgumentException

I'm running into troubles trying to sort IQueryable of my EF Entity.
My object structure is something like this:
Item
Item.CustomFieldValue [List<CustomFieldValue>]
Item.CustomFieldValue.DefinitionID
Item.CustomFieldValue.Value
and I'm working with
IQueryable<Item>
I'd need to sort it conditionally with values having desired definition id being sorted first something like this:
queryable = queryable
.OrderBy(p => p.CustomFieldValue
.Where(p2 => p2.DefinitionID == defId)
.Select(p3 => p3.Value)
.OrderBy(p4 => p4)
);
This however throws ArgumentException "DbSortClause expressions must have a type that is order comparable.".
I indeed understand what's the exception trying to say to me, I just can't figure out on how to change this so that valid query is generated.
Any help greatly appreciated
EDIT:
To bring some more light into the issue, I want to achieve something similar that this query does
SELECT * FROM ticketnumber t, customfieldvalue c
WHERE t.id like '%00000047%' and c.ticketnumberid = t.id
ORDER BY CASE
WHEN DefinitionId = 2125 THEN 1
ELSE 2
END, c.Value ASC
Alternatively, as time is starting to become a factor for me, is there a way I could append OrderBy in string form?
You probably want to use FirstOrDefault() at the end of the end of the first OrderBy so you won't be dealing with enumerables but with values.
queryable = queryable
.OrderBy(p => p.CustomFieldValue
.Where(p2 => p2.DefinitionID == defId)
.Select(p3 => p3.Value)
.OrderBy(p4 => p4)
.FirstOrDefault()
);
Modification of Joanvo's answer did the trick, this is the working code [I've removed the inner OrderBy]
queryable = queryable.OrderBy(p => p.CustomFieldValue.Where(p2 => p2.DefinitionID == defId).Select(p3 => p3.Value).FirstOrDefault());

changing linq to sql query

I have a question regarding a Linq to SQL query.
I have following situation:
I have a search with lots of options, like location, availability, name, language etc ...
For this options i have to execute a query to retrieve the results according to options selected, how can i best do it, i cannot write a linq query like for each possibility and combination of options, but i cannot write one for all of them as it will not work, for example:
from p in context.people where p.location==model.location && p.availability==model.availability .... select p
In this case imagine availability is not selected and should not be searched for, but in this case it will be passed as false, or if location is not set and is null so it will only search for empty locations, although i just need all.
So my question is how do people handle this kind of behaviour with queries?
As you long as you do not execute the linq query immediately you can just add where clauses to it. You can do this for example:
var query = from p in context.people;
if(searchOnLocation)
{
query = query.where(p => p.location == model.location);
}
if(otherSearch)
{
query = query.where(p => p.someOtherProperty == someotherValue);
}
var result = query.ToList();
As long you don't call ToList() on your IQueryable, the linq will not be translated into SQL. It's only in the last call, that the linq will be translated and executed against the database
IQueryable<Person> query = context.people;
if(model.location != null)
query = query.Where(x => x.location == model.location);
if(model.availability != null)
query = query.Where(x => x.availability == model.availability);
// etc
Basically, you can compose more and more restrictions as you go.
If you want to implement query without if condition than you can use following syntax:
var query = context.people.
where(p => p.location == (model.location ?? p.location)
&& p.availability == (model.availability ?? p.availability))
.ToList();

extract one column from a var using linq

i have something like this
var emp = db.Employees.toList();
in my employees table i have emp name, emp id and salary, using linq with lambda expressions, how do i access emp id in some another variable.
I have tried looking up for it, couldn't find a solution which does it using linq with lambda expressions
var employeeLeaves = db.Leaves
.Include("Employee")
.Include("Employee.Manager")
.Where(l => l.Status.Id == 1)
.GroupBy(l => l.Employee.Manager.Id)
.Select(l => l.GroupBy(k=>k.Employee.Id).Select(j=>j.GroupBy(‌​p=>p.GroupId)))
.ToList();
this is the actual query i have,dont ask me how i wrote it..:P now i want to get id column from employeeLeaves and store it in some another variable
It's not entirely clear what you're trying to do, which is why you've got so many answers with different approaches. If you're trying to turn the "collection of employees" into a "collection of IDs" then you want something like this:
var ids = emp.Select(x => x.Id);
Or more directly:
var ids = db.Employees.Select(x => x.Id);
(Optionally with ToList at the end of each of these.)
I would strongly advise you to learn LINQ (and the somewhat-related languages features such as var) thoroughly, from scratch, with the help of a good book or tutorial. Learning bits piecemeal by just finding samples which do something a bit like what you want is not a good approach, IMO.
var empId = db.Employees.Single(x => x.id == 5).Id;
You can use the select. Maybe something like this:
var result=db.Employees
.Select(s=>s.emp_id);
Try this syntax:
var empIds = db.Employees.Select(e=>e.EmpID)
Database.Tablename.Single(x => x.id == anyId)
This should select single row

Dynamic linq-to-sql that queries based on multiple keywords

I had been putting together a simple little search.
IEnumerable<Member> searchResults = (from m in members
where m.ScreenName.ToUpper().Contains(upperKeyword)
select m).AsEnumerable();
An then I realized this if the user typed in "keyword1 keyword2", this little query will always search for that exact string. So, I decided I should probably split keywords
string[] keywords = upperKeyword.split(' ');
and then I ran into an issue. I can't really do this:
IEnumerable<Member> searchResults = (from m in members
where m.ScreenName.ToUpper().Contains(keywords) // array of string
select m).AsEnumerable();
because .Contains() doesn't take array. How could I accomplish this?
Try this (untested):
IEnumerable<Member> searchResults = members.ToList().Where(m => keywords.Any(k => m.Summary.Contains(k)))
Edit
Added .ToList(), as I don't think LINQ will be able to convert the above into SQL, so we'll have to perform this in-memory.
For Exact Matches:
Try the inverse of what you have: where keywords.Contains(m.ScreenName)
For reference, Creating IN queries with LINQ-to-SQL
For Partial Matches:
string[] keywords = new[]{ ... };
var results = db.members.Where(m => keywords.Any(sn => m.ScreenName.Contains(sn)));
No compilation error here, but I don't have the data to test against.
I think you need to convert the array to a list. I'm just on my way out of the office, but I think this should work.
IEnumerable<Member> searchResults = (from m in members
where keywords.ToList().Contains(m.ScreenName.ToUpper()) // array of string
select m).AsEnumerable();

Categories

Resources