This question already has answers here:
C# Linq where clause as a variable
(5 answers)
Closed 4 years ago.
Im new in LINQ,i need to pass different conditions on the same LINQ query like:
var rslt = (from t in cr.faultStat
where(parameter)
select new{
name=t.Name,
Fname=t.fname
});
the parameter seen in the where ,is the part i want to send conditions dynamicaly but i dont know how,because where accepts boolean,but i want to send something like:
string parameter="date>"2018-10-10" && id="123"
generally how should i send parameter to linq dynamically
I guess (according to your comment) actually you don't have a string but you have multiple conditions. Then i'd suggest to write your query like this:
var query = cr.faultStat;
// the user selected a min-date-filter?
if(minDate.HasValue)
{
query = query.Where(x => x.Date > minDate.Value);
}
// the user selected a max-date-filter?
if(maxInclusiveDate.HasValue)
{
query = query.Where(x => x.Date <= maxInclusiveDate.Value);
}
// the user selected an id-filter?
if(id.HasValue)
{
query = query.Where(x => x.Id == id.Value);
}
var rslt = query
.Select(x => select new
{
t.name,
t.fname, ...
});
Actually after this the database (or whatever the source is) was not even queried once due to deferred execution of above methods. You have to use a foreach or a method that does it:
int resultCount = rslt.Count(); // like this
Related
This question already has answers here:
How to chain OR clauses, with LINQ?
(2 answers)
Closed 2 years ago.
I'm writing a query where, based on what input the user has provided, I need to add "disjunctive" conditions (that is to say "or" conditions). To do this with "conjunctive" conditions ("and" conditions"), this is fairly straight forward...
var employees = repository.GetAll<Employee>(); // returns IQueryable
if (!string.IsNullOrEmpty(firstName))
employees = employees.Where(e => e.FirstName.Contains(firstName));
if (!string.IsNullOrEmpty(lastName))
employees = employees.Where(e => e.LastName.Contains(lastName));
if (!string.IsNullOrEmpty(email))
employees = employees.Where(e => e.Email.Contains(email));
The resulting query will have 0 to 3 AND conditions depending on whether firstName, lastName, or email are populated. But is there a way to do this using OR conditions? For example, is there something like the following...
// Notice these use of OrWhere which does not exist...
var employees = repository.GetAll<Employee>(); // returns IQueryable
if (!string.IsNullOrEmpty(firstName))
employees = employees.OrWhere(e => e.FirstName.Contains(firstName));
if (!string.IsNullOrEmpty(lastName))
employees = employees.Orwhere(e => e.LastName.Contains(lastName));
if (!string.IsNullOrEmpty(email))
employees = employees.OrWhere(e => e.Email.Contains(email));
I know that I can make a very large where condition...
var employees = repository.GetAll<Employee>().Where(e =>
(!string.IsNullOrEmpty(firstName) && e.FirstName.Contains(firstName)) ||
(!string.IsNullOrEmpty(lastName) && e.LastName.Contains(lastName)) ||
(!string.IsNullOrEmpty(email) && e.Email.Contains(email))
);
...but the query produced is not efficient and the code does not seem as elegant to me. I'm hoping there's a better way to do this that looks more like the 2nd example.
Here is one way using OR conditions between the null check and the property filter, if that's what you're after...
var employees = repository.GetAll<Employee>(); // returns IQueryable
employees = employees.Where(e =>
(firstName == null || e.FirstName.Contains(firstName)) &&
(lastName == null || e.LastName.Contains(lastName)) &&
(email == null || e.Email.Contains(email)));
This question already has answers here:
Creating dynamic queries with entity framework
(4 answers)
Closed 3 years ago.
I've read many different variations to this question and I cannot believe the solution I need is so complicated that warrants using additional libraries and crazy tricks, hopefully not!
At runtime, the LINQ query in my project needs to change dynamically depending on how many columns in the DB table the user wants to filter by. In my example, I first show a working LINQ Query which is hard coded.
The next example uses a list that is built at runtime, all i need to figure out is how to insert the string variable (whereClause) into the LINQ Query without compile errors?
Working example (hard coded)
logs = _context.Logs.Where(s => s.Level == LogLevel & s.LogEventCategory == EventCategory)
.Select(s => new Logs()
{
TimeStamp = s.TimeStamp,
Level = s.Level,
Exception = s.Exception,
LogEventCategory = s.LogEventCategory,
LogEventType = s.LogEventType,
LogEventSource = s.LogEventSource,
LogEventName = s.LogEventName,
LogUserName = s.LogUserName,
LogForename = s.LogForename,
LogSurname = s.LogSurname,
LogData = s.LogData
});
Example Two - The solution I want to fix and use...
First create a list, the contents of the list will change each time a new query is run, strings passed as variables through the parent OnGet method will either contain a value and be used in the string join concatenation, or will be null and therefore not added to the list and used in the concatenation.
Second example is where I get compilation errors.
var filtersList = new List<string>();
if (LogLevel != null)
{
filtersList.Add("s.LogLevel == LogLevel");
}
if (EventCategory != null)
{
filtersList.Add("s.EventCategory == EventCategory");
}
var whereClause = string.Join(" & ", filtersList.ToArray());
logs = _context.Logs.Where(s => whereClause) // *HERE I WANT TO USE THE STRING VARIABLE! not working
.Select(s => new Logs()
{
TimeStamp = s.TimeStamp,
Level = s.Level,
Exception = s.Exception,
LogEventCategory = s.LogEventCategory,
LogEventType = s.LogEventType,
LogEventSource = s.LogEventSource,
LogEventName = s.LogEventName,
LogUserName = s.LogUserName,
LogForename = s.LogForename,
LogSurname = s.LogSurname,
LogData = s.LogData
});
The error I get says 'Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type' blah blah blah
You just add the .Where() calls to the end of your query, before materializing:
query = _context.Logs.Select(s => new ..);
if (EventCategory != null) query = query.Where(e => e.EventCategory == EventCategory);
if (LogLevel != null) query = query.Where(e => e.LogLevel == LogLevel);
var items = query.ToList();
This question already has answers here:
How do you add an index field to Linq results
(3 answers)
Closed 3 years ago.
SQL:
Select top percent a,b,ROW_NUMBER() over(PARTITION BY a,b order by a,b) as rowsnumber
from Students as s
group by a,b
LINQ:
var students=from p in Students
group p by new{p.a,p.b} into grp
order by grp.Key.a,grp.Key.b
.Select(s=>s.a,s.b).ToList();
I want to this SQL query convert to LINQ but not convert.
var list = FileList.Select((file, index) => new { Index=index, Filename=file });
Maybe so for example.
Like the other answer indicates, the Select method has a handy overload with the index parameter. It requires the method LINQ syntax though (and not the query syntax) So, the following query should do the trick. Note that it combines both: query and method syntax as I tried to keep it close to the code in the question above.
var studentGroups=
from p in Students
group p by new { p.a, p.b };
var students =
from gr in studentGroups
from st in Students
.Where(s => s.a == gr.Key.a && s.b == gr.Key.b)
.Select((s,i) => new { s.a, s.b, s.c, s.d, rn = i + 1 })
orderby st.a, st.b
select st;
I convert your sql query to lambda.
var students = context.GroupBy(g => new { g.A, g.B }).Select((s, index) => new {
s.Key.A,
s.Key.B,
rowsnumber = index + 1
}).Take(10).ToList();
Group by is working like partition by.
Index start from 0, so converting to row number to need add 1.
Take is select TOP 10 rows.
This question already has answers here:
Linq Syntax - Selecting multiple columns
(3 answers)
Closed 5 years ago.
I am trying to select multiple columns by using LinqToSql, but I am having a hard time with it. I am quite new in LinqToSql.
When I am selecting 1 column I do it like this:
string[] name = mycontext.Users.SingleorDefault(p => p.UserId == 1).UserName;
Is there anything similar for multiple columns?
I actually want to assign Name and Surname in a ListBox control
Use Anonymous Types:
var result = mycontext.Users.Where(p => p.UserId == 1)
.Select(c => new {c.UserName , c.Family ,...})
.SingleOrDefault();
You current request will query the whole user (select *).
In most cases, it is enough and you can access to each column separately :
var user = mycontext.Users.SingleorDefault(p => p.UserId == 1);
var userName = user.Username;
var password = user.Password;
// etc...
If you only need one (or several columns) but not the whole user, you can do it like this:
var userInfo = mycontext.Users.Where(p => p.UserId == 1).Select(p => new {p.UserName, p.Password}).SingleOrDefault();
var userName = userInfo.UserName;
var password = userInfo.Password;
If you prefer a collection of string in result, you can do it this way:
List<string> userInfo = mycontext.Users.Where(p => p.UserId == 1).Select(p => new List<string> { p.UserName, p.Password }).SingleOrDefault();
var username = userInfo[0];
var password = userInfo[1];
This way, the generated query will looks like Select UserName, Password From UserTable. Its usefull only if your table has a lots of columns or a heavy one (blob for example).
How it works: by calling the Where extension methods firstly, you tell .NET to not run the query immediately. It will be executed on the SingleOrDefault call. But at this moment, the query has been completed and the whole part is done in SQL.
Can't you return User object?
var user = mycontext.Users.SingleorDefault(p => p.UserId == 1)
After that you can get all properties of User without creating dynamic types
Hello fellow stackoverflowers,
I'm currently working on a project which gives me a bit of trouble concerning filtering data from a database by using multiple filter values. The filter happens after selecting the filters and by clicking a button.
I have 5 filters: Region, Company, Price, and 2 boolean values
Note that Region and Company are special dropdownlist with checkboxes which means the user can select one or more regions and company names.
I already made a few tests and came up with a incomplete code which works a bit but not to my liking.
Problems arise when one of my filters is NULL or empty. I don't really know how to process this. The only way i thought of was using a bunch of IF ELSE statements, but i'm starting to think that this will never end since there are so much possibilities...
I'm sure there is a far more easier way of doing this without using a bunch of IF ELSE statements, but i don't really know how to do it. If anyone could steer me in the right direction that would be appreciated. Thanks
Here is what i have right now (I haven't added the Price to the query for now):
protected void filterRepeater(List<int> regionIDs, string[] companyArray,
string blocFiltValue, bool bMutFunds, bool bFinancing)
{
DatabaseEntities db = new DatabaseEntities();
PagedDataSource pagedDsource = new PagedDataSource();
IQueryable<Blocs> query = (from q in db.Blocs
where q.isActive == true
orderby q.date descending
select q);
IQueryable<Blocs> queryResult = null;
//if some filters are NULL or Empty, it create a null queryResult
queryResult = query.Where(p => companyArray.Contains(p.company) &&
regionIDs.Contains((int)p.fkRegionID) &&
(bool)p.mutual_funds == bMutFunds &&
(bool)p.financing == bFinancing);
if (queryResult.Count() > 0)
{
//Bind new data to repeater
pagedDsource.DataSource = queryResult.ToArray();
blocRepeater.DataSource = pagedDsource;
blocRepeater.DataBind();
}
}
Only add the relevant filters to query:
IQueryable<Blocs> query =
from q in db.Blocs
where q.isActive == true
orderby q.date descending
select q;
if (companyArray != null)
{
query = query.Where(p => companyArray.Contains(p.company));
}
if (regionIDs != null)
{
query = query.Where(p => regionIDs.Contains((int)p.fkRegionID));
}
// ...
// etc
// ...
if (query.Any()) // Any() is more efficient than Count()
{
//Bind new data to repeater
pagedDsource.DataSource = query.ToArray();
blocRepeater.DataSource = pagedDsource;
blocRepeater.DataBind();
}
If you want to filter only by the filter values that are not null or empty then you can construct the query by appending the where clauses one by one:
if(companyArray != null && companyArray.Length > 0) {
query = query.Where(p => companyArray.Contains(p.company));
}
if(regionIDs!= null && regionIDs.Length > 0) {
query = query.Where(p => regionIDs.Contains((int)p.fkRegionID));
}
if (!String.IsNullOrEmpty(blocFiltValue)) {
query = query.Where(p => p.Block == blocFiltValue);
}
Also you can use nullable values for value types, if you need to filter them optionally
bool? bMutFunds = ...; // Possible values: null, false, true.
...
if(bMutFunds.HasValue) {
query = query.Where(p => (bool)p.mutual_funds == bMutFunds.Value);
}
Maybe you can create a string for the SQL sentence, and dynamically add parts to this sentence like if something was selected or checked you add something to this string when thh selection was completed by the user you can execute this SQL sentence.