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));
Related
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();
How can I make this lesser than or equal work in my .Where() clause? I am getting an error.
var filteredProducts = Products.Where(p => p.State.Contains("Bruikbaar"))
.Where(p => p.Privilege <= ui.GetPrivilegeNumber())
.ToList();
Error:
LINQ to Entities does not recognize the method 'Int32 GetPrivilegeNumber()' method, and this method cannot be translated into a store expression.
I hope this question is never asked before. Googled couldn't find it either or I am using the wrong words to express my problem.
ui.GetPrivilegeNumber() is not a recognized method.
Use this:
var uiPrivilege = ui.GetPrivilegeNumber();
var filteredProducts = Products.Where(p => p.State.Contains("Bruikbaar"))
.Where(p => p.Privilege <= uiPrivilege)
.ToList();
And as other users mentionted, you can optimize your Where.
EF does not execute method calls which you use in predicates. It stores them as expression (i.e. syntax tree) and then analyzes this tree to build SQL query by translating C# code to SQL code. It cannot translate GetPrivilegeNumber() method call into SQL, because there is no appropriate SQL code for that. So all you need is move this method call out of expression and pass only result of method call instead:
var privilegeNumber = ui.GetPrivilegeNumber();
var filteredProducts = Products.Where(p => p.State.Contains("Bruikbaar"))
.Where(p => p.Privilege <= privilegeNumber)
.ToList();
Now privilegeNumber is just an integer variable which is translated into SQL parameter
SELECT * FROM Products p
WHERE p.State LIKE '%Bruikbaar%' AND p.Privilege <= #privilegeNumber
You need to move ui.GetPrivilegeNumber() outside of the query. You can also merge those Where queries into a single one:
var privilegeNumber = ui.GetPrivilegeNumber();
var filteredProducts = Products.Where(p =>
p.State.Contains("Bruikbaar")
&& p => p.Privilege <= privilegeNumber)
.ToList();
You can use other evaluation method inside LinQ. To simplified the code, you can use it in little old way of writing LinQ.
var uiPrivilege = ui.GetPrivilegeNumber();
var filteredProducts =(from p in Products
where p.State.Contains("Bruikbaar") && p.Privilege <= uiPrivilege
select p).ToList();
The above query generate same output but easy to understood.
I want to pass a lambda to my .Select() method depending on a condition.
I set my lambda up like this:
Func<Monthly, int?> f = x => x.CLDD;
I then set up my .Select() like this:
IQueryable query =
db.Monthlies
.GroupBy(o => o.Date.Value.Year)
.Select(
o => new {
Year = o.Key,
MaxDate = o.Max(x => x.Date),
Data = o.Sum(f)
}
)
.Where(o => o.Year != currentYear)
.OrderBy(o => o.Year);
The code compiles and runs fine but the query does not send back any results. When I debug and watch query I see it says:
+ base {"Internal .NET Framework Data Provider error 1025."}
System.SystemException {System.InvalidOperationException}
Note if instead I do:
Expression<Func<Monthly, int?>> f = x => x.CLDD;
Then o.Sum(f) errors saying:
Error 1 Instance argument: cannot convert from
'System.Linq.IGrouping<int,MyWeb.Models.Monthly>' to
System.Linq.IQueryable<MyWeb.Models.Monthly>'
Thank you!
You were close, Entity Framework needs an Expression to work not Func, but the Sum extension method that receives an Expression works only with IQueryable.
Now inside Select you are getting an IGrouping from GroupBy which does not implement IQueryable only IEnumerable.
So you just need to cast it to get the right extension method:
Data = o.AsQueryable().Sum(f)
Hi I am using a linq query which is throwing the error LINQ to Entities does not recognize the method 'System.String ToString(Int32)' method, and this method cannot be translated into a store expression.
List<string> resultMap = (from item in mapResult
select Convert.ToString(item.ResultDE)).ToList();
Error is throwing in this below statement
List<Result_DE> resultList = (from result in db.Result_DE
where result.IsActive == "1"
&& resultMap.Contains(Convert.ToString(Convert.ToInt32(result.ID)))
select result).ToList();
please tell me the proper way of writing this query.
You cannot use these conversion functions in a LINQ to Entities statement, they cannot be translated to SQL, you need to do the conversions in memory. But I don't think you need to do that at all.
If you were just using the resultMap to get your resultList, filtered by Results of which the Id is present in mapResult, do the following:
var resultList = db.Result_DE
.Where(r => r.IsActive == "1" && mapResult.Any(mr => mr.ResultDE == r.ID));
.ToList();
If mapResult is an in-memory collection, instead of an IQueryable that is attached to the db context, you need to do the following:
var resultIds = mapResult.Select(mr => mr.ResultDE).ToList();
var resultList = db.Result_DE
.Where(r => r.IsActive == "1" && resultIds.Contains(r.ID));
.ToList();
Before you call any method (e.g. ToString()), you need to convert LINQ to Object using AsEnumerable().
if your item.ResultDE and result.ID is variable type of Int32,
why don directly create a List<Int32> ?
List<Int32> resultMap = (from item in mapResult
select item.ResultDE).ToList<Int32>();
List<Result_DE> resultList = (from result in db.Result_DE
where result.IsActive == "1"
&& resultMap.Contains(result.ID)
select result).ToList<Result_DE>();
Use SqlFunctions.StringConvert instead of Convert.ToString.
A similar question was asked and answered here
I need to group the table according to the Month in the table.
The query goes this way:
var query =
from a in db.Dates
from b in db.Facts
where a.Count_Key == b.Date_key
select new
{
a.Month,
b.Fact_key
};
From this query I try to group by Month
query = query.GroupBy(x => x.Month);
Grid1.DataSource = query;
Grid1.DataBind();
Then I get the following error which says:
Cannot implicitly convert IGrouping
int ? into IQueryable
You can do this:
var query2 = query.GroupBy(x => x.Month);
Grid1.DataSource = query2;
Grid1.DataBind();
The problem is caused because the var query is implicitly inferred from its usage. The query is of type IQueryable<SomeAnonymousType> and the GroupBy method returns an IQueryable<IGrouping<int?, SomeAnonymousType>>. Those are simply two different types.
You can't reassign back to the query variable as the results of those two queries are different types.
Your first query is essentially this:
IQueryable<'a> query =
from a in db.Dates
from b in db.Facts
where a.Count_Key == b.Date_key
select new
{
a.Month,
b.Fact_key
};
I.e. it returns a straight IQueryable of the anonymous type.
Your second query returns an IQueryable<IGrouping<'a>>, i.e. an IQueryable of a group of the anonymous type:
IQueryable<IGrouping<'a>> groupedQuery = query.GroupBy(x => x.Month);
Therefore because the return types are different you can't assign the result of the grouping back to the original variable.