How can I create an Lambda Expression for Linq in the Where clause for two tables after the Join?
I have this,
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
Func<MyCourse, bool> funcWhere = filter.Compile();
and then this,
var myClasses = db.MyCourse.Join(db.People, mc => mc.PersonId,
p => p.PersonId, (mc, p) => new { MyCourse= mc, Person = p }).Where(???)
The reason I need to do it this way is because if I put the filter on the MyCourse table first with,
db.MyCourse.Where(funcWhere).Join....
The SQL created brings back all of the People and all of the MyCourse and then uses the filter. If I do the where at the end,
(mc, p) => new { MyCourse= mc, Person = p }).Where(mc=>mc.MyCourse.Active == 1)
I get a good query with the Joins. Else the engine queries all the rows into memory first. Two separate queries with thousands of rows.
I have seen a tremendous amount of questions on SO and elsewhere about this. I cannot find one that tells me how to do the Expression when there is more than one table, from a Join, using a dynamic Where Expression<Func<T,TResult>>
.
The goal is to make a dynamic query statement based upon Expressions (not Dynamic Linq, and no third party.) In fact, this question claims the Where at the end is slower, but in my program it does the correct query with Joins.
MyCourse has a PersonId and People has a PersonId. If I wrote this by hand it'd look like,
select mc.CourseName, p.LastName
from MyCourse mc inner join Person p on mc.PersonId = p.PersonId
where mc.Active = 1;
(Those are just example columns for the question. They're not really what I want from the above query, except Active == 1.)
Where clause with Join in lambda expression
Update: FWIW, I was able to get it working this this,
var param = Expression.Parameter(typeof(MyClass), "MyClassDebug");
var exp = Expression.Lambda<Func<MyClass, bool>>(
Expression.Equal(
Expression.Property(param, dbParameter),
Expression.Constant(dbValue)
),
param
);
I did not do navigation properties or anything else. And I was able to use it like this,
var MyQuery = (from recs in dbcontext.MyClass.Where(exp)
...three joins
The produced SQL looked good, and the Explain plan showed minimal row retrieval.
c# entity-framework linq lambda expression-trees
|
show 5 more comments
I have this,
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
Func<MyCourse, bool> funcWhere = filter.Compile();
and then this,
var myClasses = db.MyCourse.Join(db.People, mc => mc.PersonId,
p => p.PersonId, (mc, p) => new { MyCourse= mc, Person = p }).Where(???)
The reason I need to do it this way is because if I put the filter on the MyCourse table first with,
db.MyCourse.Where(funcWhere).Join....
The SQL created brings back all of the People and all of the MyCourse and then uses the filter. If I do the where at the end,
(mc, p) => new { MyCourse= mc, Person = p }).Where(mc=>mc.MyCourse.Active == 1)
I get a good query with the Joins. Else the engine queries all the rows into memory first. Two separate queries with thousands of rows.
I have seen a tremendous amount of questions on SO and elsewhere about this. I cannot find one that tells me how to do the Expression when there is more than one table, from a Join, using a dynamic Where Expression<Func<T,TResult>>
.
The goal is to make a dynamic query statement based upon Expressions (not Dynamic Linq, and no third party.) In fact, this question claims the Where at the end is slower, but in my program it does the correct query with Joins.
MyCourse has a PersonId and People has a PersonId. If I wrote this by hand it'd look like,
select mc.CourseName, p.LastName
from MyCourse mc inner join Person p on mc.PersonId = p.PersonId
where mc.Active = 1;
(Those are just example columns for the question. They're not really what I want from the above query, except Active == 1.)
Where clause with Join in lambda expression
Update: FWIW, I was able to get it working this this,
var param = Expression.Parameter(typeof(MyClass), "MyClassDebug");
var exp = Expression.Lambda<Func<MyClass, bool>>(
Expression.Equal(
Expression.Property(param, dbParameter),
Expression.Constant(dbValue)
),
param
);
I did not do navigation properties or anything else. And I was able to use it like this,
var MyQuery = (from recs in dbcontext.MyClass.Where(exp)
...three joins
The produced SQL looked good, and the Explain plan showed minimal row retrieval.
c# entity-framework linq lambda expression-trees
Are you using Entity Framework? And isPeopleId
in yourMyCourse
table a foreign key?
– Gabriel Luci
Nov 15 '18 at 19:53
Yes. It is a foreign key in name only, not at the database defined as such.
– johnny
Nov 15 '18 at 19:59
I see. It would be easier if it was since Entity Framework would create a reference list for you from your Person class. But anyway, it is still possible to do.
– Gabriel Luci
Nov 15 '18 at 20:03
For one, the start of the query should bedb.MyCourse.Where(filter)
. But I think that depending on your EF version you should look for the various global query filter options.
– Gert Arnold
Nov 15 '18 at 20:04
@GertArnold The problem is when I use it that way, Linq brings back all the Person records, 36k and then adjusts the rows for the Active courses. If I put the filter at the end of it with the expression typed out x=>x.MyCourse.Active == 1, then I get a single query with a Join (from what I see on the SQL Profiler).
– johnny
Nov 15 '18 at 20:07
|
show 5 more comments
I have this,
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
Func<MyCourse, bool> funcWhere = filter.Compile();
and then this,
var myClasses = db.MyCourse.Join(db.People, mc => mc.PersonId,
p => p.PersonId, (mc, p) => new { MyCourse= mc, Person = p }).Where(???)
The reason I need to do it this way is because if I put the filter on the MyCourse table first with,
db.MyCourse.Where(funcWhere).Join....
The SQL created brings back all of the People and all of the MyCourse and then uses the filter. If I do the where at the end,
(mc, p) => new { MyCourse= mc, Person = p }).Where(mc=>mc.MyCourse.Active == 1)
I get a good query with the Joins. Else the engine queries all the rows into memory first. Two separate queries with thousands of rows.
I have seen a tremendous amount of questions on SO and elsewhere about this. I cannot find one that tells me how to do the Expression when there is more than one table, from a Join, using a dynamic Where Expression<Func<T,TResult>>
.
The goal is to make a dynamic query statement based upon Expressions (not Dynamic Linq, and no third party.) In fact, this question claims the Where at the end is slower, but in my program it does the correct query with Joins.
MyCourse has a PersonId and People has a PersonId. If I wrote this by hand it'd look like,
select mc.CourseName, p.LastName
from MyCourse mc inner join Person p on mc.PersonId = p.PersonId
where mc.Active = 1;
(Those are just example columns for the question. They're not really what I want from the above query, except Active == 1.)
Where clause with Join in lambda expression
Update: FWIW, I was able to get it working this this,
var param = Expression.Parameter(typeof(MyClass), "MyClassDebug");
var exp = Expression.Lambda<Func<MyClass, bool>>(
Expression.Equal(
Expression.Property(param, dbParameter),
Expression.Constant(dbValue)
),
param
);
I did not do navigation properties or anything else. And I was able to use it like this,
var MyQuery = (from recs in dbcontext.MyClass.Where(exp)
...three joins
The produced SQL looked good, and the Explain plan showed minimal row retrieval.
c# entity-framework linq lambda expression-trees
I have this,
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
Func<MyCourse, bool> funcWhere = filter.Compile();
and then this,
var myClasses = db.MyCourse.Join(db.People, mc => mc.PersonId,
p => p.PersonId, (mc, p) => new { MyCourse= mc, Person = p }).Where(???)
The reason I need to do it this way is because if I put the filter on the MyCourse table first with,
db.MyCourse.Where(funcWhere).Join....
The SQL created brings back all of the People and all of the MyCourse and then uses the filter. If I do the where at the end,
(mc, p) => new { MyCourse= mc, Person = p }).Where(mc=>mc.MyCourse.Active == 1)
I get a good query with the Joins. Else the engine queries all the rows into memory first. Two separate queries with thousands of rows.
I have seen a tremendous amount of questions on SO and elsewhere about this. I cannot find one that tells me how to do the Expression when there is more than one table, from a Join, using a dynamic Where Expression<Func<T,TResult>>
.
The goal is to make a dynamic query statement based upon Expressions (not Dynamic Linq, and no third party.) In fact, this question claims the Where at the end is slower, but in my program it does the correct query with Joins.
MyCourse has a PersonId and People has a PersonId. If I wrote this by hand it'd look like,
select mc.CourseName, p.LastName
from MyCourse mc inner join Person p on mc.PersonId = p.PersonId
where mc.Active = 1;
(Those are just example columns for the question. They're not really what I want from the above query, except Active == 1.)
Where clause with Join in lambda expression
Update: FWIW, I was able to get it working this this,
var param = Expression.Parameter(typeof(MyClass), "MyClassDebug");
var exp = Expression.Lambda<Func<MyClass, bool>>(
Expression.Equal(
Expression.Property(param, dbParameter),
Expression.Constant(dbValue)
),
param
);
I did not do navigation properties or anything else. And I was able to use it like this,
var MyQuery = (from recs in dbcontext.MyClass.Where(exp)
...three joins
The produced SQL looked good, and the Explain plan showed minimal row retrieval.
c# entity-framework linq lambda expression-trees
c# entity-framework linq lambda expression-trees
edited Nov 16 '18 at 22:59
Tetsuya Yamamoto
16.8k42242
16.8k42242
asked Nov 15 '18 at 19:44
johnnyjohnny
9,14341129210
9,14341129210
Are you using Entity Framework? And isPeopleId
in yourMyCourse
table a foreign key?
– Gabriel Luci
Nov 15 '18 at 19:53
Yes. It is a foreign key in name only, not at the database defined as such.
– johnny
Nov 15 '18 at 19:59
I see. It would be easier if it was since Entity Framework would create a reference list for you from your Person class. But anyway, it is still possible to do.
– Gabriel Luci
Nov 15 '18 at 20:03
For one, the start of the query should bedb.MyCourse.Where(filter)
. But I think that depending on your EF version you should look for the various global query filter options.
– Gert Arnold
Nov 15 '18 at 20:04
@GertArnold The problem is when I use it that way, Linq brings back all the Person records, 36k and then adjusts the rows for the Active courses. If I put the filter at the end of it with the expression typed out x=>x.MyCourse.Active == 1, then I get a single query with a Join (from what I see on the SQL Profiler).
– johnny
Nov 15 '18 at 20:07
|
show 5 more comments
Are you using Entity Framework? And isPeopleId
in yourMyCourse
table a foreign key?
– Gabriel Luci
Nov 15 '18 at 19:53
Yes. It is a foreign key in name only, not at the database defined as such.
– johnny
Nov 15 '18 at 19:59
I see. It would be easier if it was since Entity Framework would create a reference list for you from your Person class. But anyway, it is still possible to do.
– Gabriel Luci
Nov 15 '18 at 20:03
For one, the start of the query should bedb.MyCourse.Where(filter)
. But I think that depending on your EF version you should look for the various global query filter options.
– Gert Arnold
Nov 15 '18 at 20:04
@GertArnold The problem is when I use it that way, Linq brings back all the Person records, 36k and then adjusts the rows for the Active courses. If I put the filter at the end of it with the expression typed out x=>x.MyCourse.Active == 1, then I get a single query with a Join (from what I see on the SQL Profiler).
– johnny
Nov 15 '18 at 20:07
Are you using Entity Framework? And is
PeopleId
in your MyCourse
table a foreign key?– Gabriel Luci
Nov 15 '18 at 19:53
Are you using Entity Framework? And is
PeopleId
in your MyCourse
table a foreign key?– Gabriel Luci
Nov 15 '18 at 19:53
Yes. It is a foreign key in name only, not at the database defined as such.
– johnny
Nov 15 '18 at 19:59
Yes. It is a foreign key in name only, not at the database defined as such.
– johnny
Nov 15 '18 at 19:59
I see. It would be easier if it was since Entity Framework would create a reference list for you from your Person class. But anyway, it is still possible to do.
– Gabriel Luci
Nov 15 '18 at 20:03
I see. It would be easier if it was since Entity Framework would create a reference list for you from your Person class. But anyway, it is still possible to do.
– Gabriel Luci
Nov 15 '18 at 20:03
For one, the start of the query should be
db.MyCourse.Where(filter)
. But I think that depending on your EF version you should look for the various global query filter options.– Gert Arnold
Nov 15 '18 at 20:04
For one, the start of the query should be
db.MyCourse.Where(filter)
. But I think that depending on your EF version you should look for the various global query filter options.– Gert Arnold
Nov 15 '18 at 20:04
@GertArnold The problem is when I use it that way, Linq brings back all the Person records, 36k and then adjusts the rows for the Active courses. If I put the filter at the end of it with the expression typed out x=>x.MyCourse.Active == 1, then I get a single query with a Join (from what I see on the SQL Profiler).
– johnny
Nov 15 '18 at 20:07
@GertArnold The problem is when I use it that way, Linq brings back all the Person records, 36k and then adjusts the rows for the Active courses. If I put the filter at the end of it with the expression typed out x=>x.MyCourse.Active == 1, then I get a single query with a Join (from what I see on the SQL Profiler).
– johnny
Nov 15 '18 at 20:07
|
show 5 more comments
1 Answer
1
active
oldest
votes
I suspect calling Compile()
on your Expression
is causing your trouble. Your full query includes the Join
, but you've already compiled the Where
clause, so it can't compile the entire query including the Join
together. That might be why it's grabbing the entire table because it's executing the Where
by itself first, then doing the Join
later.
But you don't need to call Compile()
. Just pass the Expression
into Where()
:
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
var myClasses = db.MyCourse
.Where(filter)
.Join(db.People, mc => mc.PersonId,
p => p.PersonId, (mc, p) => new { MyCourse= mc, Person = p }).ToList();
Somewhat unrelated to your actual problem, but if you created the foreign keys, you can simplify this a bit. Update your model in your Visual Studio project if you haven't already. Your Person
class will change to have a list of MyCourse
and your MyCourse
class will have a list of Person
.
So you can do something like:
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
var courses = db.MyCourse.Include("Person").Where(filter);
foreach (var course in courses) {
var person = course.Person; //This is populated with the Person record
}
Linq handles the join, and each MyCourse
returned will have a Person
property.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53326868%2fhow-can-i-create-an-lambda-expression-for-linq-in-the-where-clause-for-two-table%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I suspect calling Compile()
on your Expression
is causing your trouble. Your full query includes the Join
, but you've already compiled the Where
clause, so it can't compile the entire query including the Join
together. That might be why it's grabbing the entire table because it's executing the Where
by itself first, then doing the Join
later.
But you don't need to call Compile()
. Just pass the Expression
into Where()
:
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
var myClasses = db.MyCourse
.Where(filter)
.Join(db.People, mc => mc.PersonId,
p => p.PersonId, (mc, p) => new { MyCourse= mc, Person = p }).ToList();
Somewhat unrelated to your actual problem, but if you created the foreign keys, you can simplify this a bit. Update your model in your Visual Studio project if you haven't already. Your Person
class will change to have a list of MyCourse
and your MyCourse
class will have a list of Person
.
So you can do something like:
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
var courses = db.MyCourse.Include("Person").Where(filter);
foreach (var course in courses) {
var person = course.Person; //This is populated with the Person record
}
Linq handles the join, and each MyCourse
returned will have a Person
property.
add a comment |
I suspect calling Compile()
on your Expression
is causing your trouble. Your full query includes the Join
, but you've already compiled the Where
clause, so it can't compile the entire query including the Join
together. That might be why it's grabbing the entire table because it's executing the Where
by itself first, then doing the Join
later.
But you don't need to call Compile()
. Just pass the Expression
into Where()
:
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
var myClasses = db.MyCourse
.Where(filter)
.Join(db.People, mc => mc.PersonId,
p => p.PersonId, (mc, p) => new { MyCourse= mc, Person = p }).ToList();
Somewhat unrelated to your actual problem, but if you created the foreign keys, you can simplify this a bit. Update your model in your Visual Studio project if you haven't already. Your Person
class will change to have a list of MyCourse
and your MyCourse
class will have a list of Person
.
So you can do something like:
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
var courses = db.MyCourse.Include("Person").Where(filter);
foreach (var course in courses) {
var person = course.Person; //This is populated with the Person record
}
Linq handles the join, and each MyCourse
returned will have a Person
property.
add a comment |
I suspect calling Compile()
on your Expression
is causing your trouble. Your full query includes the Join
, but you've already compiled the Where
clause, so it can't compile the entire query including the Join
together. That might be why it's grabbing the entire table because it's executing the Where
by itself first, then doing the Join
later.
But you don't need to call Compile()
. Just pass the Expression
into Where()
:
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
var myClasses = db.MyCourse
.Where(filter)
.Join(db.People, mc => mc.PersonId,
p => p.PersonId, (mc, p) => new { MyCourse= mc, Person = p }).ToList();
Somewhat unrelated to your actual problem, but if you created the foreign keys, you can simplify this a bit. Update your model in your Visual Studio project if you haven't already. Your Person
class will change to have a list of MyCourse
and your MyCourse
class will have a list of Person
.
So you can do something like:
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
var courses = db.MyCourse.Include("Person").Where(filter);
foreach (var course in courses) {
var person = course.Person; //This is populated with the Person record
}
Linq handles the join, and each MyCourse
returned will have a Person
property.
I suspect calling Compile()
on your Expression
is causing your trouble. Your full query includes the Join
, but you've already compiled the Where
clause, so it can't compile the entire query including the Join
together. That might be why it's grabbing the entire table because it's executing the Where
by itself first, then doing the Join
later.
But you don't need to call Compile()
. Just pass the Expression
into Where()
:
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
var myClasses = db.MyCourse
.Where(filter)
.Join(db.People, mc => mc.PersonId,
p => p.PersonId, (mc, p) => new { MyCourse= mc, Person = p }).ToList();
Somewhat unrelated to your actual problem, but if you created the foreign keys, you can simplify this a bit. Update your model in your Visual Studio project if you haven't already. Your Person
class will change to have a list of MyCourse
and your MyCourse
class will have a list of Person
.
So you can do something like:
Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
var courses = db.MyCourse.Include("Person").Where(filter);
foreach (var course in courses) {
var person = course.Person; //This is populated with the Person record
}
Linq handles the join, and each MyCourse
returned will have a Person
property.
edited Nov 15 '18 at 22:34
answered Nov 15 '18 at 20:13
Gabriel LuciGabriel Luci
11.4k11525
11.4k11525
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53326868%2fhow-can-i-create-an-lambda-expression-for-linq-in-the-where-clause-for-two-table%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Are you using Entity Framework? And is
PeopleId
in yourMyCourse
table a foreign key?– Gabriel Luci
Nov 15 '18 at 19:53
Yes. It is a foreign key in name only, not at the database defined as such.
– johnny
Nov 15 '18 at 19:59
I see. It would be easier if it was since Entity Framework would create a reference list for you from your Person class. But anyway, it is still possible to do.
– Gabriel Luci
Nov 15 '18 at 20:03
For one, the start of the query should be
db.MyCourse.Where(filter)
. But I think that depending on your EF version you should look for the various global query filter options.– Gert Arnold
Nov 15 '18 at 20:04
@GertArnold The problem is when I use it that way, Linq brings back all the Person records, 36k and then adjusts the rows for the Active courses. If I put the filter at the end of it with the expression typed out x=>x.MyCourse.Active == 1, then I get a single query with a Join (from what I see on the SQL Profiler).
– johnny
Nov 15 '18 at 20:07