How do I write the following sql query to a Predicate Expression using Fluent Sytax:
select c.* from customer c
inner join Orders r on r.CustomerId = c.Id
where
c.MemberSince > '01/01/2013' &&
r.OrderDate > '01/01/2014'
order by r.OrderDate
I am expecting something like this:
Expression<Func<Customer, bool>> filters = PredicateBuilder.True<Customer>();
filters = filters.And(x => x.MemberSince > DateTime.Parse('01/01/2013'));
filterr = ....
I am not sure how to add the Orders predicate. And then I call:
var list = db.Customers.AsExpandable().Where(filters).ToList();
You don't need PredicateBuilder at all. You just need to understand that the result of a join is effectively a sequence of pairs:
DateTime memberCutoff = ...;
DateTime orderCutoff = ...;
var query = context.Customers
.Join(context.Orders,
c => c.Id, r => r.CustomerId, (c, r) => new { c, r })
.Where(pair => pair.c.MemberSince > memberCutoff &&
pair.r.OrderDate > orderCutoff)
.OrderBy(pair => pair.r.OrderDate);
Related
I have 2 queries with LINQ first one is lambda expression and second is only standard LINQ. I want to get the same output in both, but the 2nd query doesn't give me an output.
How I can solve this and what is the logic of joining a table 2 times?
var query1 = _context.UserEdu.Where(x => x.personId == id && x.status ==PersonEducationStatus.SA.ToString())
.Join(_context.Educations.Where(x => x.statusCode == ACTIVE), pe => pe.classNum, s => s.classNum, (pe, class) => class)
.Join(_context.Educations.Where(x => x.isActive), s => s.eduNum, defaultS => defaultS.eduNum, (class, defaultclass) => new
{ class, defaultclass.classNum })
.Join(_context.EducationDocument.Where(...),
s => s.classNum,
rd => rd.entity_id,
(class, rd) => new
{
... output
});
var query2 = (from pedu in _context.UserEdu.Where(x => x.personId == id && x.status == PersonEducationStatus.SA.ToString())
join class in _context.Educations.Where(x => x.statusCode == ACTIVE) on pedu.classNum equals class.classNum
join defaultclass in _context.Educations.Where(x => x.isActive) on pedu.classNum equals defaultclass.classNum
join rd in _context.EducationDocument.Where(...) on defaultclass.classNum equals rd.entity_id
select new
{
... output same with first query
});
Well,
pedu.classNum equals defaultclass.classNum
Is not
s => s.eduNum, defaultS => defaultS.eduNum
IOW, you have used in second join different keys.
I need to translate a Linq query into Dynamic Linq but I'm having a problem with the OrderBy part.
This is the Linq query:
var q = from pp in ctx.MyEntity
join c in sortedListString on pp.CountryId.ToString() equals c.Substring(9)
orderby c ascending
select pp;
As you can see, I'm sorting by the entinty in the join.
Now I need to write the same query but with dynamic linq and I have:
var q = from pp in ctx.MyEntity
select pp;
q = q.Join(
sortedListString,
o => o.CountryId.ToString(),
i => i.Substring(9), (o, i) => o
).OrderBy(???);
What should I put in the OrderBy, knowing that I want to order by sortedListString?
Not sure what you mean by "dynamic linq" here, but equivalent of your query using "full" LINQ syntax is:
var q = ctx.MyEntity
.Join(sortedListString,
pp => pp.CountryId.ToString(),
c => c.Substring(9),
(pp, c) => new { pp, c })
.OrderBy(t => t.c)
.Select(t => t.pp);
How i can obtain the similar Linq query as this SQL query using Linq method based?
SELECT * FROM F_ARTICLE A
LEFT JOIN F_ARTFOURNISS AF ON AF.AR_Ref = A.AR_Ref AND AF.AF_Principal = 1
ORDER BY A.AR_Design DESC
OFFSET 500 ROWS FETCH NEXT 100 ROWS ONLY
I'm using method based due to System.Linq.Dynamic requirements.
The mapping is like this:
I started by this but i don't know how to limit to AF_Principal = 1:
var query = context.F_ARTICLE
.Join(
context.F_ARTFOURNISS,
a => a.AR_Ref,
t => t.AR_Ref,
(a, t) => new { a, t })
.Select(
z => new ArticleItem()
{
Article = z.a,
Tarif = z.t.FirstOrDefault()
})
.OrderBy($"{field} {direction}");
return query.Skip(startIndex).Take(count).ToList();
The code is from my head but the point is using DefaultIfEmpty for doing LEFT JOIN:
var query = from farticle in context.F_ARTICLE
join b in context.F_ARTFOURNISS
on new {farticle.AR_Ref, AF_Principal = 1} equals new {b.AR_Ref, b.AF_Principal} into gj
from subres in gj.DefaultIfEmpty()
select farticle;
return query.Skip(startIndex).Take(count).ToList();
Also you can limit by AF_Principal using Where clause (I think DBMS engine will optimize the query anyway)
see if this works
var query = from F1 in context.F_ARTICLE join F2 in context.F_ARTFOURNISS
on F1.AR_Ref equals F2.AR_Ref into newF
from F3 in newF.where(f=>f.AF_Principal == 1).DefaultIfEmpty()
select f;
return query.Skip(startIndex).Take(count).ToList();
I think i found the query:
var query = context.F_ARTICLE
.GroupJoin(
context.F_ARTFOURNISS,
a => a.AR_Ref,
t => t.AR_Ref,
(a, t) => new { a, t })
.Select(
z => new ArticleItem()
{
Article = z.a,
Tarif = z.t.Where(t=>t.AF_Principal == 1).FirstOrDefault()
})
.OrderBy($"{field} {direction}");
return query.Skip(startIndex).Take(count).ToList();
I would like to create a LINQ join statement equivalent of a Left Join
My tables are set up like so:
Recipe
RecipeID
...
Instruction
RecipeID
StepID
SomeFlag
...
Equivalent SQL:
SELECT *
FROM Recipe r
LEFT JOIN Instruction i
ON r.RecipeID = i.RecipeID
AND SomeFlag > 0
This is what I have so far:
var tmp = db.Recipe
.GroupJoin(
db.Instruction,
r => r.RecipeID,
i => i.RecipeID,
(r, i) => new {r, i},
???);
Firstly, is GroupJoin the correct choice for this type of operation? From what I understand, Join is equivalent to the SQL 'Inner Join' and GroupJoin is equivalent to 'Left Join'. Second, what is the correct syntax to obtain my desired result? I have been searching for a while and I can't seem to find a suitable answer using extension methods.
Don't forget to read the help from (GroupJoin: MSDN http://msdn.microsoft.com/en-us/library/bb535047.aspx and Join MSDN http://msdn.microsoft.com/fr-fr/library/bb534675.aspx)
The last argument of the GroupJoin and Join is optional (by overload) and is not usually used.
It is a function that allow you to specify how to compare r.RecipeID with i.RecipeID. As RecipeID must be an integer, using the default comparer is a good choice. So let it with:
var tmp = db.Recipe
.Join(db.Instruction,
r => r.RecipeID,
i => i.RecipeID,
(r, i) => new {r, i});
Now what you want to have is to remove all the instructions that have SomeFlag > 0. Why not do this before joining?
Like this:
var tmp = db.Recipe
.Join(db.Instruction.Where(instruction => instruction.SomeFlag > 0),
r => r.RecipeID,
i => i.RecipeID,
(r, i) => new {r, i});
Update
#usr has perfectly commented saying Join performs an INNER JOIN.
As you may have remarked, LINQ does not have different methods for INNER, OUTER, LEFT, RIGHT joins. To know the equivalent LINQ of a particular SQL join you may find help on MSDN ( http://msdn.microsoft.com/en-us/library/vstudio/bb397676.aspx ).
var tmp = from recipe in Recipes
join instruction in
from instruction in Instructions
where instruction.SomeFlag > 0
select instruction
on recipe.RecipeID equals instruction.RecipeID into gj
from instruction in gj.DefaultIfEmpty()
select new
{
recipe,
instruction
};
using extension methods it is a bit of an ugly solution:
var tmp = Recipes.GroupJoin(Instructions.Where(instruction => instruction.SomeFlag > 0),
recipe => recipe.RecipeID,
instruction => instruction.RecipeID,
(recipe, gj) => new { recipe, gj })
.SelectMany(#t => #t.gj.DefaultIfEmpty(),
(#t, instruction) => new
{
#t.recipe,
instruction
});
Please tell me if I did't understand you, but this extension method returns the same result that you priveded in sql.
public static IEnumerable<ResultType> GetLeftJoinWith(this IEnumerable<Recipe>, IEnumerable<Instructions> ins)
{
var filteredInstructions = ins.Where(x => x.SomeFlag > 0);
var res = from r in rec
join tmpIns in filteredInstructions on r.RecipeID equals t.RecipeID into instructions
from instruction in instructions.DefaultIfEmpty()
select new { r, instruction };
return res;
}
try this
var model = db.Recipe
.GroupJoin(db.Instructions.Where(instruction => instruction.SomeFlag > 0),r => r.RecipeID,i => i.RecipeID, (r, i) => new { Recipe = r, Instructions = i })
.SelectMany(t => t.Instructions.DefaultIfEmpty(),(t, Instructions) => new
{
Recipe = t.Recipe,
Instructions = Instructions
});
Consider this LINQ expression written using query notation:
List<Person> pr = (from p in db.Persons
join e in db.PersonExceptions
on p.ID equals e.PersonID
where e.CreatedOn >= fromDate
orderby e.CreatedOn descending
select p)
.ToList();
Question: how would you write this LINQ expression using dot notation?
Like this:
List<Person> pr = db.Persons
.Join(db.PersonExceptions,
p => p.ID,
e => e.PersonID,
(p, e) => new { p, e })
.Where(z => z.e.CreatedOn >= fromDate)
.OrderByDescending(z => z.e.CreatedOn)
.Select(z => z.p)
.ToList();
Note how a new anonymous type is introduced to carry both the p and e bits forward. In the specification, query operators which do this use transparent identifiers to indicate the behaviour.