My simple SQL query is
select *
from deletedCards
where cardNumber in (select cardNum from cardInformation
where country = 'NP')
and I need to write it in C#. I've come this far :
var Query1 = dbContext.deletedCards;
Query1.Where(x => dbContext.cardInformation.Where(a => a.country== 'NP')).Select(a => a.cardNum).Contains(x => x.cardNumber);
but this is showing an error
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
Can anybody help me write the query correctly? Thanks!
You didn't filter anything in your Where method also your Contains method is not right, try this way.
var npCardNums = dbContext.cardInformation.Where(a => a.country == 'NP')
.Select(a => a.cardNum);
var query1 = dbcontext.deletedCards.Where(x => npCardNums.Contains(x.CardNumber));
I will suggest you to read Language Integrated Query (LINQ) section on MSDN.
You can use join also
var ans= from dc in deletedcards
join CI in cardInformation on dc.cardnum equals CI.cardNum
where CI.coumtry='NP' select dc
Try like this.
var Query1 = dbContext.deletedCards;
Query1.Where(x=> dbContext.cardInformation.Where(a=>a.country== 'NP').Contains(x=>x.cardNumber)).Select(a=>a.cardNum).ToList();
Related
I want to convert the following query to LINQ equivalent. I've gone through this but unable to acheive my results which has Max. can anyone help me in this regard.
Below is my SQL Query:
select max(a.amount_limit) as AmountLimit from tbl_AmountEmpRole a where a.Role_Name in(select b.Role_name from tbl_UserRoles b where Emp_id=4)
Thanks in Advance
Assuming a variable called context, this should work:
context.tbl_AmountEmpRole
.Where(er => context.tbl_UserRoles.Where(ur => ur.Emp_id == 4).Select(ur => ur.Role_Name).Contains(er.Role_Name))
.Max(er => er.amount_limit);
However, I believe you might be able to rewrite your query using a JOIN:
SELECT MAX(a.amount_limit) as AmountLimit FROM tbl_AmountEmpRole a
INNER JOIN tbl_UserRoles b
ON a.Role_Name = b.Role_Name
WHERE b.Emp_id = 4
In which case you could use the Join method:
context.tbl_AmountEmpRole.Join(context.tbl_UserRoles, er => er.Role_Name, ur => ur.Role_Name, new { er, ur })
.Where(j => j.ur.Emp_id = 4)
.Max(j => j.er.amount_limit);
Make sure to double-check syntax and signatures. I wrote this from memory.
You can try somthing like this :
var role_names=tbl_UserRoles.Where(x=> x.Emp_id==4).Select(x=>x.Role_name);
var MaxacountLimit=tbl_AmountEmpRole.Where(y=>role_names.contains(y))
.Max(z=>z.amount_limit);
The following returns Cannot convert lambda expression to type 'bool' because it is not a delegate type
var Products = from s in db.Products where
( from c in s.Manufacturers
where (x => (from man in model.man where man.HasValue select man.Value).Contains(c.ManufacturerID)
select c).Any()
select s;
While this just works
if (model.man != null)
{
var students = from s in db.Products
where (from c in s.Manufacturers
where model.man.Contains(c.ManufacturerID)
select c).Any()
select s;
}
What am i doing wrong in the first case?
The model.man is declared as
public int?[] man { get; set; }
You can use null conditional access instead (in C# 6)
var students = from s in db.Products
where (from c in s.Manufacturers
where model.man?.Contains(c.ManufacturerID) ?? false
select c).Any()
select s;
Edit: added ?? false because there is no implicit conversion between bool and bool?
Like Rahul says, you cannot mix query and method syntax. This should compile:
var Products = from s in db.Products
where(from c in s.Manufacturers
where (from man in model.man
where man.HasValue
select man.Value)
.Contains(c.ManufacturerID)
select c).Any()
select s;
If you want to use a lambda expression at that particular point, you can always chain it with a period, e.g.:
var Products = from s in db.Products
where(s.Manufacturers
.Where(c => (from man in model.man
where man.HasValue
select man.Value)
.Contains(c.ManufacturerID))).Any()
select s;
Although as personal preference (readability), I'd rather not mix the two syntaxes. If you are unfamiliar with method syntax, ReSharper does provide the option to convert query to method chain (hammer icon).
I too got the same error in a simple for loop. The error was due to the misplaced "=" symbol.
It was
for(int i=10;i=>0;i--)
{
//your code
}
If you look at the code closely you can see that = is placed in front of >.
It should be less than or equal to that is >=.
The correct code should be
for(int i=10;i>=0;i--)
{
//your code
}
I hope this might help someone.
I'm trying write this sql query to Linq:
SQL:
select c.course_name, count(s.s_name) as studenti from course c
join study_group g on g.course_id=c.id
join student s on s.study_group_id=g.id
group by c.course_name;
Linq:
var countStudents = (from s in ado.student //on g.id equals s.study_group_id
join g in ado.study_group on s.study_group_id equals g.id
join c in ado.course on g.course_id equals c.id
group s by c.course_name into cn
let count = cn.Count(co => co.s_name)
select new
{
c.course_name
course_name = cn.Key
});
and still I have an error at co => co.s_name
Error: Cannot implicitly convert type 'string' to 'bool'
Know anybody how to fix this ?
Thank you.
The SQL COUNT(column) aggregate function only counts not null values. The equivalent in LINQ would be to replace the line:
let count = cn.Count(co => co.s_name)
by
let count = cn.Count(co => co.s_name != null)
Of course, no guarantees on the generated SQL here. Either way, it is strange that a student's name may be null, though I have no intention of discussing your model.
Note
You won't be able to retrieve the desired count unless you select it in your code. Also, do check if students' names can be null, because in case they can't, just a cn.Count() would suffice.
Why do you need the Count clause in your LINQ statement? Just use a .Count() extension method on the IEnumerable that's returned from your query to get the count.
var count = countStudents.Count();
So I tried to follow this example to have a sub-query in the where clause of this LINQ query.
var innerquery =
from app in context.applications
select new { app.app_id };
IEnumerable<postDatedCheque> _entityList = context.postDatedCheques
.Where(e => innerquery.Contains(e.appSancAdvice.application.app_id));
The objective was to select those records from postDatedCheques that have app_id in applications table.
But I am getting following erros inside the where clause:
Delegate 'System.Func' does not
take 1 arguments
Cannot convert lambda expression to type 'string' because it is not
a delegate type
'System.Linq.IQueryable' does not contain a
definition for 'Contains' and the best extension method overload
'System.Linq.ParallelEnumerable.Contains(System.Linq.ParallelQuery,
TSource)' has some invalid arguments
Instance argument: cannot convert from
'System.Linq.IQueryable' to
'System.Linq.ParallelQuery'
What am I coding incorrect?
I think a simple join would do the job. It will filter out the 'cheques' that have no relative 'app':
var _entitylist =
from cheque in context.postDatedCheques
join app in context.applications on cheque.appSancAdvice.application equals app
select cheque;
Edit:
Solutions using a .Contains(...) will be translated into a SQL IN statement. Which will be very inefficient. Linq join is translated into SQL INNER JOIN which is very efficient if your DB schema is well trimmed (FKs, index)
What about?
IEnumerable<postDatedCheque> _entityList = context.postDatedCheques.Where(
e => context.applications.Any(
x => e.appSancAdvice.application.app_id == x.app_id));
And if you want to use two statements, set the first as an expression function.
Expression<Func<string, bool>> innerQuery =
x => context.applications.Any(y => y.app_id == x);
IEnumerable<postDatedCheque _entityList =
context.postDatedCheques.Where(
x => innerQuery(x.appSancAdvice.application.app_id));
innerquery is a IQueryable of anonymous type that contains an app_id.
The line Contains(e.appSancAdvice.application.app_id) doesn't make sense since e.appSancAdvice.application.app_id and the anonymous type are not the same type.
Simply do:
var _entityList = context.postDatedCheques
.Where(e =>
context.applications
.Select(a => a.app_id)
.Contains(e.appSancAdvice.application.app_id));
Try this instead:
var innerquery =
from app in context.applications
select new { app.app_id };
IEnumerable<postDatedCheque> _entityList = context.postDatedCheques
.Where(e => innerquery.Any(a => a.app_id == e.appSansAdvice.application.app_id));
I want to have a dynamic where condition.
In the following example:
var opportunites = from opp in oppDC.Opportunities
join org in oppDC.Organizations
on opp.OrganizationID equals org.OrgnizationID
where opp.Title.StartsWith(title)
select new
{
opp.OpportunityID,
opp.Title,
opp.PostedBy,
opp.Address1,
opp.CreatedDate,
org.OrganizationName
};
Some times I have Title and sometimes I don't. And also I want to add date in where clause dynamically.
For example, like this SQL:
string whereClause;
string SQL = whereClause == string.Empty ?
"Select * from someTable" : "Select * from someTable" + whereclause
You can rewrite it like this:
var opportunites = from opp in oppDC.Opportunities
join org in oppDC.Organizations on opp.OrganizationID equals org.OrgnizationID
select new
{
opp.OpportunityID,
opp.Title,
opp.PostedBy,
opp.Address1,
opp.CreatedDate,
org.OrganizationName
};
if(condition)
{
opportunites = opportunites.Where(opp => opp.Title.StartsWith(title));
}
EDIT: To answer your question in the comments, yes, you can keep appending to the original Queryable. Remember, this is all lazily executed, so at this point all it's doing it building up the IQueryable so you can keep chaining them together as needed:
if(!String.IsNullOrEmpty(title))
{
opportunites = opportunites.Where(.....);
}
if(!String.IsNullOrEmpty(name))
{
opportunites = opportunites.Where(.....);
}
You can dynamically add a where clause to your IQueryable expression like this:
var finalQuery = opportunities.Where( x => x.Title == title );
and for the date similarly.
However, you will have to wait to create your anonymous type until after you've finished dynamically added your where clauses if your anonymous type doesn't contain the fields you want to query for in your where clause.
So you might have something that looks like this:
var opportunities = from opp in oppDC.Opportunities
join org in oppDC.Organizations on
opp.OrganizationID equals org.OrgnizationID
select opp
if(!String.IsNullOrEmpty(title))
{
opportunities = opportunities.Where(opp => opp.Title == title);
}
//do the same thing for the date
opportunities = from opp in opportunities
select new
{
opp.OpportunityID,
opp.Title,
opp.PostedBy,
opp.Address1,
opp.CreatedDate,
org.OrganizationName
};
The WHERE clause could be done something like
//...
where string.IsNullOrEmpty(title) ? true : opp.Title.StartsWith(title)
//...
Dynamically returning records I don't think is possible in LINQ since it needs to be able to create a consistent AnonymousType (in the background)
Because queries are composable, you can just build the query in steps.
var query = table.Selec(row => row.Foo);
if (someCondition)
{
query = query.Where(item => anotherCondition(item));
}
If you know in advance all possible where queries like in the SQL example you have given you can write the query like this
from item in Items
where param == null ? true : ni.Prop == param
select item;
if you don't know all possible where clauses in advance you can add where dymically for example like this:
query = query.Where(item => item.ID != param);
The following questions and answers address this quite well:
Dynamic where clause in LINQ - with column names available at runtime
Is there a pattern using Linq to dynamically create a filter?
I was searching for creating a dynamic where clause in LINQ and came across a very beautifull solution on the web which uses ExpressionBuilder in C#.
I am posting it here since none of the above solution uses this approach. It helped me. Hope it helps you too
http://www.codeproject.com/Tips/582450/Build-Where-Clause-Dynamically-in-Linq