Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AuthorDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ public class AuthorDTO
public int AuthorAge { get; set; }
public string AuthorCountry { get; set; }
public string AuthorNickName { get; set; }
}
}
}
21 changes: 21 additions & 0 deletions AuthorDTO_Simple.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Collections.Generic;

namespace OptimizeMePlease
{
public class AuthorDTO_Simple
{
//public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string Country { get; set; }
//public string NickName { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
//public int UserId { get; set; }
//public int RoleId { get; set; }
public int BooksCount { get; set; }
public IEnumerable<BookDto_Meaningful> AllBooks { get; set; }

}
}
75 changes: 71 additions & 4 deletions BenchmarkService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using BenchmarkDotNet.Attributes;
using Microsoft.EntityFrameworkCore;
using OptimizeMePlease.Context;
using System;
using System.Collections.Generic;
using System.Linq;

Expand All @@ -19,7 +20,7 @@ public BenchmarkService()
/// and all his/her books (Book Name/Title and Publishment Year) published before 1900
/// </summary>
/// <returns></returns>
[Benchmark]
//[Benchmark]
public List<AuthorDTO> GetAuthors()
{
using var dbContext = new AppDbContext();
Expand Down Expand Up @@ -85,12 +86,78 @@ public List<AuthorDTO> GetAuthors()
return finalAuthors;
}

[Benchmark]
//[Benchmark]
public List<AuthorDTO> GetAuthors_Optimized()
{
List<AuthorDTO> authors = new List<AuthorDTO>();
using var dbContext = new AppDbContext();

var authors = dbContext.Authors
.AsNoTracking()
.Where(x => x.Country == "Serbia" && x.Age == 27)
.OrderByDescending(b => b.BooksCount)
.Take(2)
.Include(x => x.User)
.ThenInclude(x => x.UserRoles)
.Include(x => x.Books)
.ThenInclude(x => x.Publisher)
.Select(x => new AuthorDTO
{
UserCreated = x.User.Created,
UserEmailConfirmed = x.User.EmailConfirmed,
UserFirstName = x.User.FirstName,
UserLastActivity = x.User.LastActivity,
UserLastName = x.User.LastName,
UserEmail = x.User.Email,
UserName = x.User.UserName,
UserId = x.User.Id,
RoleId = x.User.UserRoles.SingleOrDefault(y => y.UserId == x.UserId).RoleId,
BooksCount = x.BooksCount,
AllBooks = x.Books.Where(b => b.Published.Year < 1900).Select(y => new BookDto
{
Id = y.Id,
Name = y.Name,
Published = y.Published,
ISBN = y.ISBN,
PublisherName = y.Publisher.Name,
PublishedYear = y.Published.Year
}).ToList(),
AuthorAge = x.Age,
AuthorCountry = x.Country,
AuthorNickName = x.NickName,
Id = x.Id
});

return authors.ToList();
}

return authors;

[Benchmark]
public List<AuthorDTO_Simple> GetAuthors_Optimized_Meaningful()
{
using var dbContext = new AppDbContext();
var date = new DateTime(1900, 1, 1);
return dbContext.Authors
.Include(x => x.Books.Where(b => b.Published < date))
.AsNoTracking()
.Where(x => x.Country == "Serbia" && x.Age == 27)
.OrderByDescending(x => x.BooksCount)
.Take(2)
.Select(x => new AuthorDTO_Simple
{
FirstName = x.User.FirstName,
LastName = x.User.LastName,
Email = x.User.Email,
UserName = x.User.UserName,
BooksCount = x.BooksCount,
AllBooks = x.Books.Select(y => new BookDto_Meaningful
{
Name = y.Name,
PublishedYear = y.Published
}),
Age = x.Age,
Country = x.Country,
})
.ToList();
}
}
}
2 changes: 1 addition & 1 deletion BookDto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ public class BookDto
public int PublishedYear { get; set; }
public string PublisherName { get; set; }
public string ISBN { get; set; }
}
}
}
13 changes: 13 additions & 0 deletions BookDto_Meaningful.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;

namespace OptimizeMePlease
{
public class BookDto_Meaningful
{
//public int Id { get; set; }
public string Name { get; set; }
public DateTime PublishedYear { get; set; }
//public string PublisherName { get; set; }
//public string ISBN { get; set; }
}
}
2 changes: 1 addition & 1 deletion Context/AppDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class AppDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer("Server=localhost;Database=OptimizeMePlease;Trusted_Connection=True;Integrated Security=true;MultipleActiveResultSets=true");
options.UseSqlServer("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=master;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;Database=OptimizeMePlease");
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
Expand Down
10 changes: 5 additions & 5 deletions OptimizeMePlease.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
<PackageReference Include="Bogus" Version="34.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.29" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.29" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.29" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.29">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
22 changes: 22 additions & 0 deletions OptimizeMePlease.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OptimizeMePlease", "OptimizeMePlease.csproj", "{BD7CFAC4-DEF7-4A49-BA9A-39D891961236}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BD7CFAC4-DEF7-4A49-BA9A-39D891961236}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD7CFAC4-DEF7-4A49-BA9A-39D891961236}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD7CFAC4-DEF7-4A49-BA9A-39D891961236}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BD7CFAC4-DEF7-4A49-BA9A-39D891961236}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
13 changes: 9 additions & 4 deletions Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,23 @@ public class Program
static void Main(string[] args)
{
//Debugging
BenchmarkService benchmarkService = new BenchmarkService();
benchmarkService.GetAuthors();
//BenchmarkService benchmarkService = new BenchmarkService();
// Original query
//var nonOpt = benchmarkService.GetAuthors();
// Optimized query without uchanging the dto
//var Opt = benchmarkService.GetAuthors_Optimized();
// Optimized query with changing DTOs
//var Opt_Meaningful = benchmarkService.GetAuthors_Optimized_Meaningful();

//Comment me after first execution, please.
//IWillPopulateData();

//BenchmarkRunner.Run<BenchmarkService>();
BenchmarkRunner.Run<BenchmarkService>();
}

public static void IWillPopulateData()
{
string sqlConnectionString = @"Server=localhost;Database=OptimizeMePlease;Trusted_Connection=True;Integrated Security=true;MultipleActiveResultSets=true";
string sqlConnectionString = @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=master;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;Database=OptimizeMePlease";

string workingDirectory = Environment.CurrentDirectory;
string path = Path.Combine(Directory.GetParent(workingDirectory).Parent.Parent.FullName, @"script.sql");
Expand Down
54 changes: 2 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,3 @@
# OptimizeMePlease
### Note: In GetAuthors_Optimized_Meaningful I edited the DTOs to a more meaningful one including only the properties that are necessary (In my opinion).

## You are probably here because you saw my post on Linkedin.
## Welcome!

# Steps

- Before you run an application, you will need to create a database (I'm using MSSQL) named "OptimizeMePlease"
- Go to Program.cs class
- "IWillPopulateDate()" is a method which will get a script from the project directory and run in on created DB
- Run application in Debug/Release mode
- Comment or delete IWillPopulateData() call from Main method
- Go to BenchmarkService.cs class
- Start coding within GetAuthors_Optimized method

# How do I submit my solution?

- Send me a Linkedin message with your github username, I will add you and create a branch for you.

### OR

- Clone the project, create a branch and work on that branch.

### OR

- If you don't want to bother with github, after you're done with the changes, send me the results on Linkedin.

# Rules

- Only Entity Framework (Core) is allowed for using
- The data obtained in the non-optimized version of the code must also be obtained in the optimized version
- If you see potential optimization of something else, you can do it
- Entities and DbContext cannot be changed (you got legacy code no matter what it might be bad :) )
- The models returned from the method can be changed

# What should the method return?

- Given that there is a predefined database of data, the method should in any case return the list of data currently returned by the non-optimized method.

# How will performance success be measured?

- Given that each of us works on a computer with different performance and power, the execution time quotient of the non-optimized and optimized method will be checked for each separately.

Example:

Non-optimized method Execution time: 1.1s = 1100ms
Optimized method Execution time: 200ms

### Result: 1100ms/200ms = 5.5x faster.

In addition, I will check the performance on my computer for individual results.

# GOOD LUCK!
![image](https://user-images.githubusercontent.com/64654197/193173418-097870d8-b93f-41fe-b89a-dee5d9ebbb13.png)