Entity framework performance when using methods in the select clause
I'm looking at the SQL generated when performing simple select queries. I'm using code first with the sample blog context from nuget.
If the following is run:
BlogContext _context = new BlogContext();
var comments = _context.Comments.Select(c => new CommentReadOnly {Author = c.Author});
var count = comments.Count();
The following SQL is produced:
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[Comments] AS [Extent1]
) AS [GroupBy1]
Where the count is performed in the SQL which is expected.
However if I change the code to look like this:
BlogContext _context = new BlogContext();
var comments = _context.Comments.Select(c => new CommentReadOnly {Author = c.Author});
var count = comments.Count();
private CommentReadOnly ToCommentReadOnly(Comment comment)
{
return new CommentReadOnly
{
Author = comment.Author,
};
}
The following SQL is produced:
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[PostID] AS [PostID],
[Extent1].[Text] AS [Text],
[Extent1].[Author] AS [Author]
FROM [dbo].[Comments] AS [Extent1]
With the count
done in code.
The reason (I think) is because the first is returned as IQueryable
where as the second is IEnumerable
.
Is it possible to return the second query as IQueryable without executing the SQL?
The reason I ask is that I'm creating a generic repository layer that can query my entities and convert them to the required type (in the example above comment might have a couple of different 'readonly' objects). I don't want the SQL executing so early as paging may be done or other filtering in different situations.
entity-framework entity-framework-4.1 code-first
add a comment |
I'm looking at the SQL generated when performing simple select queries. I'm using code first with the sample blog context from nuget.
If the following is run:
BlogContext _context = new BlogContext();
var comments = _context.Comments.Select(c => new CommentReadOnly {Author = c.Author});
var count = comments.Count();
The following SQL is produced:
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[Comments] AS [Extent1]
) AS [GroupBy1]
Where the count is performed in the SQL which is expected.
However if I change the code to look like this:
BlogContext _context = new BlogContext();
var comments = _context.Comments.Select(c => new CommentReadOnly {Author = c.Author});
var count = comments.Count();
private CommentReadOnly ToCommentReadOnly(Comment comment)
{
return new CommentReadOnly
{
Author = comment.Author,
};
}
The following SQL is produced:
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[PostID] AS [PostID],
[Extent1].[Text] AS [Text],
[Extent1].[Author] AS [Author]
FROM [dbo].[Comments] AS [Extent1]
With the count
done in code.
The reason (I think) is because the first is returned as IQueryable
where as the second is IEnumerable
.
Is it possible to return the second query as IQueryable without executing the SQL?
The reason I ask is that I'm creating a generic repository layer that can query my entities and convert them to the required type (in the example above comment might have a couple of different 'readonly' objects). I don't want the SQL executing so early as paging may be done or other filtering in different situations.
entity-framework entity-framework-4.1 code-first
Aren't the two code snippets exactly the same? The query is excuted with.Count()
and I see no difference in the code before.Count()
.
– Slauma
Oct 19 '11 at 16:09
add a comment |
I'm looking at the SQL generated when performing simple select queries. I'm using code first with the sample blog context from nuget.
If the following is run:
BlogContext _context = new BlogContext();
var comments = _context.Comments.Select(c => new CommentReadOnly {Author = c.Author});
var count = comments.Count();
The following SQL is produced:
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[Comments] AS [Extent1]
) AS [GroupBy1]
Where the count is performed in the SQL which is expected.
However if I change the code to look like this:
BlogContext _context = new BlogContext();
var comments = _context.Comments.Select(c => new CommentReadOnly {Author = c.Author});
var count = comments.Count();
private CommentReadOnly ToCommentReadOnly(Comment comment)
{
return new CommentReadOnly
{
Author = comment.Author,
};
}
The following SQL is produced:
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[PostID] AS [PostID],
[Extent1].[Text] AS [Text],
[Extent1].[Author] AS [Author]
FROM [dbo].[Comments] AS [Extent1]
With the count
done in code.
The reason (I think) is because the first is returned as IQueryable
where as the second is IEnumerable
.
Is it possible to return the second query as IQueryable without executing the SQL?
The reason I ask is that I'm creating a generic repository layer that can query my entities and convert them to the required type (in the example above comment might have a couple of different 'readonly' objects). I don't want the SQL executing so early as paging may be done or other filtering in different situations.
entity-framework entity-framework-4.1 code-first
I'm looking at the SQL generated when performing simple select queries. I'm using code first with the sample blog context from nuget.
If the following is run:
BlogContext _context = new BlogContext();
var comments = _context.Comments.Select(c => new CommentReadOnly {Author = c.Author});
var count = comments.Count();
The following SQL is produced:
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[Comments] AS [Extent1]
) AS [GroupBy1]
Where the count is performed in the SQL which is expected.
However if I change the code to look like this:
BlogContext _context = new BlogContext();
var comments = _context.Comments.Select(c => new CommentReadOnly {Author = c.Author});
var count = comments.Count();
private CommentReadOnly ToCommentReadOnly(Comment comment)
{
return new CommentReadOnly
{
Author = comment.Author,
};
}
The following SQL is produced:
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[PostID] AS [PostID],
[Extent1].[Text] AS [Text],
[Extent1].[Author] AS [Author]
FROM [dbo].[Comments] AS [Extent1]
With the count
done in code.
The reason (I think) is because the first is returned as IQueryable
where as the second is IEnumerable
.
Is it possible to return the second query as IQueryable without executing the SQL?
The reason I ask is that I'm creating a generic repository layer that can query my entities and convert them to the required type (in the example above comment might have a couple of different 'readonly' objects). I don't want the SQL executing so early as paging may be done or other filtering in different situations.
entity-framework entity-framework-4.1 code-first
entity-framework entity-framework-4.1 code-first
edited Nov 19 '18 at 16:38
Cœur
17.4k9103145
17.4k9103145
asked Oct 19 '11 at 15:44
lancscoder
5,29973865
5,29973865
Aren't the two code snippets exactly the same? The query is excuted with.Count()
and I see no difference in the code before.Count()
.
– Slauma
Oct 19 '11 at 16:09
add a comment |
Aren't the two code snippets exactly the same? The query is excuted with.Count()
and I see no difference in the code before.Count()
.
– Slauma
Oct 19 '11 at 16:09
Aren't the two code snippets exactly the same? The query is excuted with
.Count()
and I see no difference in the code before .Count()
.– Slauma
Oct 19 '11 at 16:09
Aren't the two code snippets exactly the same? The query is excuted with
.Count()
and I see no difference in the code before .Count()
.– Slauma
Oct 19 '11 at 16:09
add a comment |
2 Answers
2
active
oldest
votes
I don't see any difference in those two queries. However, I guess you want to return a IQueryable object to the client so the client can perform further filtering and get the count from there.
You can simply return the object without doing the select and let the client do the rest.
return _context.Comments
The client can perform additional filtering on this IQueryable object
add a comment |
I think in your second query you execute the function ToCommentReadOnly() so this can't be done entirely in SQL and you end up with a Linq To Objects (IEnumerable).
But you state that you want to return an IQueryable from your Repository. This is not a recommended practice! The code to access the data should be hidden inside your repository otherwhise you will run into problems.
Say for example that your repository (which encapsulates your ObjectContext) goes out of scope after which you try to enumerate the IQueryable result the repository gave you. This will throw an error because the IQueryable can't be executed anymore.
If you expose an IQueryable from your Repository you give the end user of your Repository all the freedom they want in building their own queries, which is the thing you want to avoid by adding a repository!
So returning an IEnumerable from your Repository is a good thing :)
I would not agree that exposingIQueryable
and a context reference outside of the respository is generally "not a recommended practice". There are as many reason in favor to do so (simplicity, direct projection into ViewModels, handling large data and data virtualization in desktop apps, lazy loading, etc.) as against this practice.
– Slauma
Oct 19 '11 at 19:33
Well one example is when you are trying to optimize your queries. In our repositories we use CompiledQueries for performance. If we would expose IQueryable instead of IEnumerable, the compiling would be useless if the users of the repository would alter the queries and use the precompiling. And by using IQueryable you also couples your your code to the Entity Framework. The whole idea of the Repository pattern is to be independent of your persistent mechanism. We expose POCO's or custom DTO's from our data layer which suit the needs of the upper layers.
– Wouter de Kort
Oct 19 '11 at 19:55
I know :) These are the good points and the theory always sounds good. But rarely the costs in practice (in time and development effort) are mentioned when it comes to "Independency of persistence mechanism" and encapsulation of data access. Don't misunderstand me, I don't say that your points are never correct, but I disagree that the points are always correct.
– Slauma
Oct 19 '11 at 20:22
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%2f7824056%2fentity-framework-performance-when-using-methods-in-the-select-clause%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I don't see any difference in those two queries. However, I guess you want to return a IQueryable object to the client so the client can perform further filtering and get the count from there.
You can simply return the object without doing the select and let the client do the rest.
return _context.Comments
The client can perform additional filtering on this IQueryable object
add a comment |
I don't see any difference in those two queries. However, I guess you want to return a IQueryable object to the client so the client can perform further filtering and get the count from there.
You can simply return the object without doing the select and let the client do the rest.
return _context.Comments
The client can perform additional filtering on this IQueryable object
add a comment |
I don't see any difference in those two queries. However, I guess you want to return a IQueryable object to the client so the client can perform further filtering and get the count from there.
You can simply return the object without doing the select and let the client do the rest.
return _context.Comments
The client can perform additional filtering on this IQueryable object
I don't see any difference in those two queries. However, I guess you want to return a IQueryable object to the client so the client can perform further filtering and get the count from there.
You can simply return the object without doing the select and let the client do the rest.
return _context.Comments
The client can perform additional filtering on this IQueryable object
answered Oct 19 '11 at 18:02
MNIK
80131020
80131020
add a comment |
add a comment |
I think in your second query you execute the function ToCommentReadOnly() so this can't be done entirely in SQL and you end up with a Linq To Objects (IEnumerable).
But you state that you want to return an IQueryable from your Repository. This is not a recommended practice! The code to access the data should be hidden inside your repository otherwhise you will run into problems.
Say for example that your repository (which encapsulates your ObjectContext) goes out of scope after which you try to enumerate the IQueryable result the repository gave you. This will throw an error because the IQueryable can't be executed anymore.
If you expose an IQueryable from your Repository you give the end user of your Repository all the freedom they want in building their own queries, which is the thing you want to avoid by adding a repository!
So returning an IEnumerable from your Repository is a good thing :)
I would not agree that exposingIQueryable
and a context reference outside of the respository is generally "not a recommended practice". There are as many reason in favor to do so (simplicity, direct projection into ViewModels, handling large data and data virtualization in desktop apps, lazy loading, etc.) as against this practice.
– Slauma
Oct 19 '11 at 19:33
Well one example is when you are trying to optimize your queries. In our repositories we use CompiledQueries for performance. If we would expose IQueryable instead of IEnumerable, the compiling would be useless if the users of the repository would alter the queries and use the precompiling. And by using IQueryable you also couples your your code to the Entity Framework. The whole idea of the Repository pattern is to be independent of your persistent mechanism. We expose POCO's or custom DTO's from our data layer which suit the needs of the upper layers.
– Wouter de Kort
Oct 19 '11 at 19:55
I know :) These are the good points and the theory always sounds good. But rarely the costs in practice (in time and development effort) are mentioned when it comes to "Independency of persistence mechanism" and encapsulation of data access. Don't misunderstand me, I don't say that your points are never correct, but I disagree that the points are always correct.
– Slauma
Oct 19 '11 at 20:22
add a comment |
I think in your second query you execute the function ToCommentReadOnly() so this can't be done entirely in SQL and you end up with a Linq To Objects (IEnumerable).
But you state that you want to return an IQueryable from your Repository. This is not a recommended practice! The code to access the data should be hidden inside your repository otherwhise you will run into problems.
Say for example that your repository (which encapsulates your ObjectContext) goes out of scope after which you try to enumerate the IQueryable result the repository gave you. This will throw an error because the IQueryable can't be executed anymore.
If you expose an IQueryable from your Repository you give the end user of your Repository all the freedom they want in building their own queries, which is the thing you want to avoid by adding a repository!
So returning an IEnumerable from your Repository is a good thing :)
I would not agree that exposingIQueryable
and a context reference outside of the respository is generally "not a recommended practice". There are as many reason in favor to do so (simplicity, direct projection into ViewModels, handling large data and data virtualization in desktop apps, lazy loading, etc.) as against this practice.
– Slauma
Oct 19 '11 at 19:33
Well one example is when you are trying to optimize your queries. In our repositories we use CompiledQueries for performance. If we would expose IQueryable instead of IEnumerable, the compiling would be useless if the users of the repository would alter the queries and use the precompiling. And by using IQueryable you also couples your your code to the Entity Framework. The whole idea of the Repository pattern is to be independent of your persistent mechanism. We expose POCO's or custom DTO's from our data layer which suit the needs of the upper layers.
– Wouter de Kort
Oct 19 '11 at 19:55
I know :) These are the good points and the theory always sounds good. But rarely the costs in practice (in time and development effort) are mentioned when it comes to "Independency of persistence mechanism" and encapsulation of data access. Don't misunderstand me, I don't say that your points are never correct, but I disagree that the points are always correct.
– Slauma
Oct 19 '11 at 20:22
add a comment |
I think in your second query you execute the function ToCommentReadOnly() so this can't be done entirely in SQL and you end up with a Linq To Objects (IEnumerable).
But you state that you want to return an IQueryable from your Repository. This is not a recommended practice! The code to access the data should be hidden inside your repository otherwhise you will run into problems.
Say for example that your repository (which encapsulates your ObjectContext) goes out of scope after which you try to enumerate the IQueryable result the repository gave you. This will throw an error because the IQueryable can't be executed anymore.
If you expose an IQueryable from your Repository you give the end user of your Repository all the freedom they want in building their own queries, which is the thing you want to avoid by adding a repository!
So returning an IEnumerable from your Repository is a good thing :)
I think in your second query you execute the function ToCommentReadOnly() so this can't be done entirely in SQL and you end up with a Linq To Objects (IEnumerable).
But you state that you want to return an IQueryable from your Repository. This is not a recommended practice! The code to access the data should be hidden inside your repository otherwhise you will run into problems.
Say for example that your repository (which encapsulates your ObjectContext) goes out of scope after which you try to enumerate the IQueryable result the repository gave you. This will throw an error because the IQueryable can't be executed anymore.
If you expose an IQueryable from your Repository you give the end user of your Repository all the freedom they want in building their own queries, which is the thing you want to avoid by adding a repository!
So returning an IEnumerable from your Repository is a good thing :)
answered Oct 19 '11 at 18:36
Wouter de Kort
29.9k85791
29.9k85791
I would not agree that exposingIQueryable
and a context reference outside of the respository is generally "not a recommended practice". There are as many reason in favor to do so (simplicity, direct projection into ViewModels, handling large data and data virtualization in desktop apps, lazy loading, etc.) as against this practice.
– Slauma
Oct 19 '11 at 19:33
Well one example is when you are trying to optimize your queries. In our repositories we use CompiledQueries for performance. If we would expose IQueryable instead of IEnumerable, the compiling would be useless if the users of the repository would alter the queries and use the precompiling. And by using IQueryable you also couples your your code to the Entity Framework. The whole idea of the Repository pattern is to be independent of your persistent mechanism. We expose POCO's or custom DTO's from our data layer which suit the needs of the upper layers.
– Wouter de Kort
Oct 19 '11 at 19:55
I know :) These are the good points and the theory always sounds good. But rarely the costs in practice (in time and development effort) are mentioned when it comes to "Independency of persistence mechanism" and encapsulation of data access. Don't misunderstand me, I don't say that your points are never correct, but I disagree that the points are always correct.
– Slauma
Oct 19 '11 at 20:22
add a comment |
I would not agree that exposingIQueryable
and a context reference outside of the respository is generally "not a recommended practice". There are as many reason in favor to do so (simplicity, direct projection into ViewModels, handling large data and data virtualization in desktop apps, lazy loading, etc.) as against this practice.
– Slauma
Oct 19 '11 at 19:33
Well one example is when you are trying to optimize your queries. In our repositories we use CompiledQueries for performance. If we would expose IQueryable instead of IEnumerable, the compiling would be useless if the users of the repository would alter the queries and use the precompiling. And by using IQueryable you also couples your your code to the Entity Framework. The whole idea of the Repository pattern is to be independent of your persistent mechanism. We expose POCO's or custom DTO's from our data layer which suit the needs of the upper layers.
– Wouter de Kort
Oct 19 '11 at 19:55
I know :) These are the good points and the theory always sounds good. But rarely the costs in practice (in time and development effort) are mentioned when it comes to "Independency of persistence mechanism" and encapsulation of data access. Don't misunderstand me, I don't say that your points are never correct, but I disagree that the points are always correct.
– Slauma
Oct 19 '11 at 20:22
I would not agree that exposing
IQueryable
and a context reference outside of the respository is generally "not a recommended practice". There are as many reason in favor to do so (simplicity, direct projection into ViewModels, handling large data and data virtualization in desktop apps, lazy loading, etc.) as against this practice.– Slauma
Oct 19 '11 at 19:33
I would not agree that exposing
IQueryable
and a context reference outside of the respository is generally "not a recommended practice". There are as many reason in favor to do so (simplicity, direct projection into ViewModels, handling large data and data virtualization in desktop apps, lazy loading, etc.) as against this practice.– Slauma
Oct 19 '11 at 19:33
Well one example is when you are trying to optimize your queries. In our repositories we use CompiledQueries for performance. If we would expose IQueryable instead of IEnumerable, the compiling would be useless if the users of the repository would alter the queries and use the precompiling. And by using IQueryable you also couples your your code to the Entity Framework. The whole idea of the Repository pattern is to be independent of your persistent mechanism. We expose POCO's or custom DTO's from our data layer which suit the needs of the upper layers.
– Wouter de Kort
Oct 19 '11 at 19:55
Well one example is when you are trying to optimize your queries. In our repositories we use CompiledQueries for performance. If we would expose IQueryable instead of IEnumerable, the compiling would be useless if the users of the repository would alter the queries and use the precompiling. And by using IQueryable you also couples your your code to the Entity Framework. The whole idea of the Repository pattern is to be independent of your persistent mechanism. We expose POCO's or custom DTO's from our data layer which suit the needs of the upper layers.
– Wouter de Kort
Oct 19 '11 at 19:55
I know :) These are the good points and the theory always sounds good. But rarely the costs in practice (in time and development effort) are mentioned when it comes to "Independency of persistence mechanism" and encapsulation of data access. Don't misunderstand me, I don't say that your points are never correct, but I disagree that the points are always correct.
– Slauma
Oct 19 '11 at 20:22
I know :) These are the good points and the theory always sounds good. But rarely the costs in practice (in time and development effort) are mentioned when it comes to "Independency of persistence mechanism" and encapsulation of data access. Don't misunderstand me, I don't say that your points are never correct, but I disagree that the points are always correct.
– Slauma
Oct 19 '11 at 20:22
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2f7824056%2fentity-framework-performance-when-using-methods-in-the-select-clause%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
Aren't the two code snippets exactly the same? The query is excuted with
.Count()
and I see no difference in the code before.Count()
.– Slauma
Oct 19 '11 at 16:09