<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Telmo Rodrigues, Author at Blog IT</title>
	<atom:link href="https://blogit.create.pt/author/telmorodrigues/feed/" rel="self" type="application/rss+xml" />
	<link>https://blogit.create.pt/author/telmorodrigues/</link>
	<description>Create IT blogger community</description>
	<lastBuildDate>Tue, 08 Mar 2022 13:09:27 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>
	<item>
		<title>Smaller .NET 6 docker images</title>
		<link>https://blogit.create.pt/telmorodrigues/2022/03/08/smaller-net-6-docker-images/</link>
					<comments>https://blogit.create.pt/telmorodrigues/2022/03/08/smaller-net-6-docker-images/#respond</comments>
		
		<dc:creator><![CDATA[Telmo Rodrigues]]></dc:creator>
		<pubDate>Tue, 08 Mar 2022 12:07:30 +0000</pubDate>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[docker]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12634</guid>

					<description><![CDATA[<p>Introduction This post compares different strategies to dockerize a .NET 6 application and how to create a &#60; 100mb docker image to host a .NET 6 asp.net web application. Using the docker multi stage builds feature and a self-contained .NET with some build options the final docker image can be reduced from 760mb to 83mb, [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/telmorodrigues/2022/03/08/smaller-net-6-docker-images/">Smaller .NET 6 docker images</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Introduction</h2>



<p>This post compares different strategies to dockerize a .NET 6 application and how to create a &lt; 100mb docker image to host a .NET 6 asp.net web application. Using the docker multi stage builds feature and a self-contained .NET with some build options the final docker image can be reduced from 760mb to 83mb, almost 10x smaller!</p>



<p>All the images used were taken from the official Microsoft .NET docker <a href="https://hub.docker.com/_/microsoft-dotnet">repository</a>.</p>



<p></p>



<h2 class="wp-block-heading">1. .NET 6 SDK image</h2>



<p>Let&#8217;s start with a simple Dockerfile based on the official .NET 6 SDK build image.</p>



<pre class="wp-block-code"><code>FROM mcr.microsoft.com/dotnet/sdk:6.0
WORKDIR /app

COPY . ./

RUN dotnet publish "WebApi.csproj" -c Release -o /app/publish

ENTRYPOINT &#091;"dotnet", "/app/publish/WebApi.dll"]</code></pre>



<pre class="wp-block-code"><code>$ docker build -t api-aspnet .
$ docker images api-aspnet
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
api-aspnet   latest    700870327c08   1 weeks ago   761MB
</code></pre>



<p>We are using a docker single stage build using the base .net sdk image. After building the image we can see that the final image size is 761mb. Let&#8217;s try to check where the space is being used. For that we can use the docker history to see the layers created for this image.</p>



<pre class="wp-block-code"><code>$ docker history api-aspnet
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
700870327c08   1 weeks ago    ENTRYPOINT &#091;"dotnet" "/app/publish/WebApi.dl…   0B        buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    RUN /bin/sh -c dotnet publish "WebApi.csproj…   4.18MB    buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    RUN /bin/sh -c dotnet build -c Release # bui…   12.2MB    buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    COPY . ./ # buildkit                            721kB     buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    RUN /bin/sh -c dotnet restore # buildkit        28.2MB    buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    COPY WebApi.csproj ./ # buildkit                327B      buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    WORKDIR /app                                    0B        buildkit.dockerfile.v0
&lt;missing&gt;      2 months ago   /bin/sh -c powershell_version=7.2.1     &amp;&amp; c…   40.6MB
&lt;missing&gt;      2 months ago   /bin/sh -c curl -fSL --output dotnet.tar.gz …   392MB
&lt;missing&gt;      2 months ago   /bin/sh -c apt-get update     &amp;&amp; apt-get ins…   74.8MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV ASPNETCORE_URLS= DOTN…   0B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop) COPY dir:a54b266469a09b122…   20.3MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV ASPNET_VERSION=6.0.1 …   0B
&lt;missing&gt;      2 months ago   /bin/sh -c ln -s /usr/share/dotnet/dotnet /u…   24B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop) COPY dir:6c537cc098876a5f6…   70.6MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV DOTNET_VERSION=6.0.1     0B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV ASPNETCORE_URLS=http:…   0B
&lt;missing&gt;      2 months ago   /bin/sh -c apt-get update     &amp;&amp; apt-get ins…   37MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  CMD &#091;"bash"]                 0B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop) ADD file:09675d11695f65c55…   80.4MB
</code></pre>



<figure class="wp-block-table is-style-regular"><table><tbody><tr><td>base image</td><td>20%</td></tr><tr><td>.NET SDK + runtime</td><td>60%</td></tr><tr><td>Linux libs</td><td>15%</td></tr><tr><td>Web App source + compiled code</td><td>25%</td></tr></tbody></table></figure>



<p>The .NET SDK + runtime takes most of the space, around 60%. So let&#8217;s try to shrink it.</p>



<p></p>



<h2 class="wp-block-heading">2. .NET 6 SDK image + docker multi stage build</h2>



<p>The previous section showed us that the .NET SDK + runtime takes most of the space of the final image. This is because we are using the same docker base image to build and to run the app so the final image has all the things needed to compile and run the app. Using a docker multi stage build we can cut the .NET SDK from the final image and use it only to build our app and include only the .NET runtime in the final image to run the application.</p>



<pre class="wp-block-code"><code>FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /app

COPY . ./

RUN dotnet publish "WebApi.csproj" -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS runtime

WORKDIR /app
COPY --from=build /app/publish .

ENTRYPOINT &#091;"dotnet", "WebApi.dll"]</code></pre>



<p>Here we define 2 images: the <code>build</code> image used to compile the app which includes all the things needed to build our .NET 6 application and the final one, the <code>runtime</code>&nbsp; which only includes the .NET runtime to run our app. The first one to use for development (which contained everything needed to build your application), and a slimmed-down one to use for production, which only contained your compiled code and what is needed to run it. With multi-stage builds, you use multiple&nbsp;<code>FROM</code>&nbsp;statements in your Dockerfile. Each&nbsp;<code>FROM</code>&nbsp;instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image.</p>



<pre class="wp-block-code"><code>$ docker build -t api-aspnet-multistage .
$ docker images api-aspnet-multistage
REPOSITORY              TAG       IMAGE ID       CREATED       SIZE
api-aspnet-multistage   latest    1021a94feca4   1 weeks ago   212MB
</code></pre>



<p>Bang, we reduced our image to 212mb, this is because the complete SDK was removed from the final image.<br>Let&#8217;s see again the layers and the space being used for each one:</p>



<pre class="wp-block-code"><code>USER@DESKTOP-BJUBV5T MINGW64 ~/Documents/sonae/identitymanager-credenciaiscontinente (fix/invalid-account-association-check)
$ docker history api-aspnet-multistage
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
1021a94feca4   1 weeks ago    ENTRYPOINT &#091;"dotnet" "WebApi.dll"]              0B        buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    COPY /app/publish . # buildkit                  4.18MB    buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    WORKDIR /app                                    0B        buildkit.dockerfile.v0
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop) COPY dir:a54b266469a09b122…   20.3MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV ASPNET_VERSION=6.0.1 …   0B
&lt;missing&gt;      2 months ago   /bin/sh -c ln -s /usr/share/dotnet/dotnet /u…   24B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop) COPY dir:6c537cc098876a5f6…   70.6MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV DOTNET_VERSION=6.0.1     0B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV ASPNETCORE_URLS=http:…   0B
&lt;missing&gt;      2 months ago   /bin/sh -c apt-get update     &amp;&amp; apt-get ins…   37MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  CMD &#091;"bash"]                 0B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop) ADD file:09675d11695f65c55…   80.4MB
</code></pre>



<figure class="wp-block-table is-style-regular"><table><tbody><tr><td>base image</td><td>50%</td></tr><tr><td>.NET runtime</td><td>40%</td></tr><tr><td>Web App source + compiled code</td><td>10%</td></tr></tbody></table></figure>



<p>Let´s try to reduce the bigger part, the base image.</p>



<p></p>



<h2 class="wp-block-heading">3. Multi stage build with Alpine linux Microsoft official image</h2>



<p>We can change our base image to use the Alpine Linux instead of the default one Debian bullsyeye which is the base image of the most of the official Microsoft .NET docker images.</p>



<p></p>



<pre class="wp-block-code"><code>FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build
WORKDIR /app

COPY . ./
RUN dotnet publish "WebApi.csproj" -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine

WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT &#091;"dotnet", "WebApi.dll"]</code></pre>



<pre class="wp-block-code"><code>docker build -t api-multi-alpine .
docker images api-multi-alpine
REPOSITORY         TAG       IMAGE ID       CREATED       SIZE
api-multi-alpine   latest    0c7f1c3b0bfa   1 weeks ago   104MB
</code></pre>



<pre class="wp-block-code"><code>$ docker history api-multi-alpine
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
0c7f1c3b0bfa   1 weeks ago    ENTRYPOINT &#091;"dotnet" "WebApi.dll"]              0B        buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    COPY /app/publish . # buildkit                  4.12MB    buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    WORKDIR /app                                    0B        buildkit.dockerfile.v0
&lt;missing&gt;      2 months ago   /bin/sh -c wget -O aspnetcore.tar.gz https:/…   20.3MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV ASPNET_VERSION=6.0.1 …   0B
&lt;missing&gt;      2 months ago   /bin/sh -c wget -O dotnet.tar.gz https://dot…   69.8MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV DOTNET_VERSION=6.0.1     0B
&lt;missing&gt;      3 months ago   /bin/sh -c #(nop)  ENV ASPNETCORE_URLS=http:…   0B
&lt;missing&gt;      3 months ago   /bin/sh -c apk add --no-cache         ca-cer…   4.35MB
&lt;missing&gt;      3 months ago   /bin/sh -c #(nop)  CMD &#091;"/bin/sh"]              0B
&lt;missing&gt;      3 months ago   /bin/sh -c #(nop) ADD file:762c899ec0505d1a3…   5.61MB
</code></pre>



<figure class="wp-block-table is-style-regular"><table><tbody><tr><td>base image</td><td>10%</td></tr><tr><td>.NET runtime</td><td>80%</td></tr><tr><td>Web App source + compiled code</td><td>10%</td></tr></tbody></table></figure>



<p>Using the alpine instead of the debian base image we were able to reduce our base image size to 10% of our final image.<br>Now the .NET runtime is the part that is using most of the space of our image so let&#8217;s try to reduce this part.</p>



<p></p>



<h2 class="wp-block-heading">4. Raw alpine with a trim-self-contained and trimmed .NET build</h2>



<p>Instead of using the official Microsoft Alpine image which comes with the full .NET runtime we can use the vanilla Alpine base image and build our App using the .NET self-contained build <code>PublishSingleFile</code>  option.<br>Publishing our app as self-contained produces an application that includes the .NET runtime and libraries in a single binary, so we don&#8217;t have to use the .NET runtime installed on our base system.</p>



<p><br>We can also use the <code>PublishTrimmed</code>  option while building and publishing our app. With this options the final binary includes only a subset of the .NET framework assemblies, the assemblies that are referenced by our app. The other ones are removed from the final procuded binary file. However, there is a risk that the build-time analysis of the application can cause failures at run time, due to not being able to reliably analyze various problematic code patterns (largely centered on reflection use). To mitigate these problems, warnings are produced whenever the trimmer cannot fully analyze a code pattern. For information on what the trim warnings mean and how to resolve them, see Introduction to trim warnings.</p>



<p><br>Also, with a self-contained build we also need to specify the target platform which the final binary will be compiled. In this case we are using the alpine-x64 because our base image is the Alpine Linux.</p>



<pre class="wp-block-code"><code>FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build
WORKDIR /app

COPY . ./

RUN dotnet publish "WebApi.csproj" -c Release -o /app/publish \
    --runtime alpine-x64 \
    --self-contained true \
    /p:PublishTrimmed=true \
    /p:TrimMode=Link \
    /p:PublishSingleFile=true

FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine

WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT &#091;"./WebApi"]</code></pre>



<pre class="wp-block-code"><code>
docker build -t api-multi-alpine-raw .
docker images api-multi-alpine-raw</code></pre>



<pre class="wp-block-code"><code>$ docker history api-multi-alpine-raw
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
ac78719fc09a   1 weeks ago    ENTRYPOINT &#091;"./WebApi"]                         0B        buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    COPY /app/publish . # buildkit                  42.2MB    buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    WORKDIR /app                                    0B        buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    RUN /bin/sh -c apk add --no-cache libstdc++ …   35.5MB    buildkit.dockerfile.v0
&lt;missing&gt;      3 months ago   /bin/sh -c #(nop)  CMD &#091;"/bin/sh"]              0B
&lt;missing&gt;      3 months ago   /bin/sh -c #(nop) ADD file:8f5bc5ce64ef781ad…   5.59MB
</code></pre>



<p>The final image was reduced to 83mb because it only includes the Alpine base image and a single binary that includes our WebApp compiled code and the assemblies that are referenced by our app!</p>



<p></p>



<h2 class="wp-block-heading">References</h2>



<p><a href="https://docs.docker.com/develop/develop-images/multistage-build/">https://docs.docker.com/develop/develop-images/multistage-build/</a><br><a href="https://docs.microsoft.com/en-us/dotnet/core/deploying/">https://docs.microsoft.com/en-us/dotnet/core/deploying/</a><br><a href="https://docs.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained">https://docs.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained</a></p>



<p><a href="https://hub.docker.com/_/microsoft-dotnet">https://hub.docker.com/_/microsoft-dotnet</a></p>
<p>The post <a href="https://blogit.create.pt/telmorodrigues/2022/03/08/smaller-net-6-docker-images/">Smaller .NET 6 docker images</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/telmorodrigues/2022/03/08/smaller-net-6-docker-images/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>.NET EF Core 6 support for groupby top(n) queries</title>
		<link>https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/</link>
					<comments>https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/#respond</comments>
		
		<dc:creator><![CDATA[Telmo Rodrigues]]></dc:creator>
		<pubDate>Fri, 04 Feb 2022 16:14:46 +0000</pubDate>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[Sql]]></category>
		<category><![CDATA[entity framework]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12605</guid>

					<description><![CDATA[<p>EF Core 6 comes with some GroupBy queries improvements. In this post I wanna talk about the improvements related to &#8220;group by top(n)&#8221; queries. Let&#8217;s say we have the following table Documents: and that we want to get the two most recent documents for each user. For instance, if we have the following records: the [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/">.NET EF Core 6 support for groupby top(n) queries</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>EF Core 6 comes with some GroupBy queries improvements. In this post I wanna talk about the improvements related to &#8220;group by top(n)&#8221; queries.</p>



<p></p>



<p></p>



<p>Let&#8217;s say we have the following table Documents:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
CREATE TABLE &#x5B;dbo].&#x5B;Documents](
    &#x5B;Id] &#x5B;integer] PRIMARY KEY,
    &#x5B;UserId] &#x5B;integer] NOT NULL,
    &#x5B;Title] &#x5B;nvarchar](50) NOT NULL,
    &#x5B;Body] &#x5B;nvarchar](250) NOT NULL,
    &#x5B;CreatedOn] &#x5B;datetime] NOT NULL
)
</pre></div>


<p>and that we want to get the two most recent documents for each user. For instance, if we have the following records:</p>



<figure class="wp-block-image size-full is-resized"><img fetchpriority="high" decoding="async" src="https://blogit.create.pt/wp-content/uploads/2022/02/image-6.png" alt="" class="wp-image-12606" width="523" height="183" srcset="https://blogit.create.pt/wp-content/uploads/2022/02/image-6.png 523w, https://blogit.create.pt/wp-content/uploads/2022/02/image-6-300x105.png 300w" sizes="(max-width: 523px) 100vw, 523px" /></figure>



<p>the query should return</p>



<figure class="wp-block-image size-full"><img decoding="async" width="520" height="146" src="https://blogit.create.pt/wp-content/uploads/2022/02/image-7.png" alt="" class="wp-image-12607" srcset="https://blogit.create.pt/wp-content/uploads/2022/02/image-7.png 520w, https://blogit.create.pt/wp-content/uploads/2022/02/image-7-300x84.png 300w" sizes="(max-width: 520px) 100vw, 520px" /></figure>



<p>To do this query using EF Core and LINQ we can try to group the Documents by UserId and then sort each group by the CreatedOn column to pick the first two documents for each user.</p>



<p>We can start by trying to group all documents for each user</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
 var usersDocs = await ctx
        .Documents
        .GroupBy(doc =&gt; doc.UserId)
</pre></div>


<p>and then for each group we try to sort its elements by the CreatedOn column</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
    var usersDocs = await ctx
        .Documents
        .GroupBy(doc =&gt; doc.UserId)
        .SelectMany(userDocs =&gt; userDocs.OrderByDescending(doc =&gt; doc.CreatedOn).Take(2))
        .ToArrayAsync();
</pre></div>


<p>If we try to execute this query using a previous version of EF Core 6 we get the following error:</p>



<p></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
    .OrderByDescending(doc =&amp;gt; doc.CreatedOn)&#039; could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to &#039;AsEnumerable&#039;, &#039;AsAsyncEnumerable&#039;, &#039;ToList&#039;, or &#039;ToListAsync&#039;. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.&#039;
</pre></div>


<p></p>



<p>This is because the previous versions of EF don&#8217;t know how to translate the GroupBy inner expressions to sql. After following their suggestion I ended up with this query</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
    var usersDocs = await ctx
        .Documents
        .Select(doc =&gt; doc.UserId)
        .Distinct()
        .SelectMany(userId =&gt; 
            ctx
            .Documents
            .Where(doc =&gt; doc.UserId == userId)
            .OrderByDescending(doc =&gt; doc.CreatedOn)
            .Take(2)
        )
        .ToArrayAsync();
</pre></div>


<p>However this query has two main issues. It does a distinct over the UserId column, loads all the user ids to application memory and then it does a query for each user resulting in a n+1 query problem.</p>



<p>One way to solve these issues is to forget LINQ and rewrite the query using raw sql with a partition by UserId and the ROW_NUMBER() window funtion, doing a CTE .</p>



<p>Now, with the EF Core 6 we can use the first version of the query, since the EF Core team has added the support for translating some GroupBy inner expressions and it can translate this LINQ query to a single sql query.</p>



<p></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
    var usersDocs = await ctx
        .Documents
        .GroupBy(doc =&gt; doc.UserId)
        .SelectMany(userDocs =&gt; userDocs.OrderByDescending(doc =&gt; doc.CreatedOn).Take(2))
        .ToArrayAsync();
</pre></div>


<p>You can read more about these features and other improvements added to GroupBy queries&nbsp;<a href="https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-6.0/whatsnew#improved-groupby-support">here</a>&nbsp;and check the related github issues&nbsp;<a href="https://github.com/dotnet/efcore/issues/12088">12088</a>&nbsp;<a href="https://github.com/dotnet/efcore/issues/13805">13805</a>&nbsp;</p>



<p>Happy coding!</p>
<p>The post <a href="https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/">.NET EF Core 6 support for groupby top(n) queries</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
