Last active
June 12, 2019 06:01
-
-
Save JimBobSquarePants/932f555c803fd41c1bee96722cd7bdcd to your computer and use it in GitHub Desktop.
Comparison of EF query mapping approaches.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (176ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] | |
SELECT CASE | |
WHEN EXISTS ( | |
SELECT 1 | |
FROM [Customers] AS [x]) | |
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) | |
END | |
--Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (185ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] | |
SELECT COUNT(*) | |
FROM [Customers] AS [x] | |
--Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (77ms) [Parameters=[@__p_0='?' (DbType = | |
Int32), @__p_1='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30'] | |
SELECT [x].[Id], [x].[Email], [x].[FirstName], [x].[LastName] | |
FROM [Customers] AS [x] | |
ORDER BY [x].[LastName], [x].[FirstName] DESC, [x].[Id] | |
OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY | |
--Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (86ms) [Parameters=[@__p_0='?' (DbType = Int32), @__p_1='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30'] | |
SELECT [t].[LastName], [t].[FirstName], [t].[Id], [x.School].[Name] AS [Item1], [x.CustomerSchools].[SchoolId] AS [Item2], [x.CustomerSchools].[CustomerId] | |
FROM [CustomerSchool] AS [x.CustomerSchools] | |
INNER JOIN [Schools] AS [x.School] ON [x.CustomerSchools].[SchoolId] = [x.School].[Id] | |
INNER JOIN ( | |
SELECT [x0].[LastName], [x0].[FirstName], [x0].[Id] | |
FROM [Customers] AS [x0] | |
ORDER BY [x0].[LastName], [x0].[FirstName] DESC, [x0].[Id] | |
OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY | |
) AS [t] ON [x.CustomerSchools].[CustomerId] = [t].[Id] | |
ORDER BY [t].[LastName], [t].[FirstName] DESC, [t].[Id] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (182ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] | |
SELECT CASE | |
WHEN EXISTS ( | |
SELECT 1 | |
FROM [Customers] AS [x]) | |
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) | |
END | |
--Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (155ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] | |
SELECT COUNT(*) | |
FROM [Customers] AS [x] | |
--Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (124ms) [Parameters=[@__p_0='?' (DbType = Int32), @__p_1='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30'] | |
SELECT [x].[Id], [x].[CreateDateUtc], [x].[Email], [x].[FirstName], [x].[LandLine], [x].[LastName], [x].[Title], [x].[UpdateDateUtc] | |
FROM [Customers] AS [x] | |
ORDER BY [x].[LastName], [x].[FirstName] DESC, [x].[Id] | |
OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY | |
--Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (150ms) [Parameters=[@__p_0='?' (DbType = Int32), @__p_1='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30'] | |
SELECT [x.CustomerSchools].[CustomerId], [x.CustomerSchools].[SchoolId], [c.School].[Id], [c.School].[Address], [c.School].[CreateDateUtc], [c.School].[CreateUser], [c.School].[DPID], [c.School].[DeniedReason], [c.School].[Name], [c.School].[OldId], [c.School].[Status], [c.School].[SuburbId], [c.School].[UpdateDateUtc], [c.School].[UpdateUser] | |
FROM [CustomerSchool] AS [x.CustomerSchools] | |
INNER JOIN [Schools] AS [c.School] ON [x.CustomerSchools].[SchoolId] = [c.School].[Id] | |
INNER JOIN ( | |
SELECT [x0].[Id], [x0].[LastName], [x0].[FirstName] | |
FROM [Customers] AS [x0] | |
ORDER BY [x0].[LastName], [x0].[FirstName] DESC, [x0].[Id] | |
OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY | |
) AS [t] ON [x.CustomerSchools].[CustomerId] = [t].[Id] | |
ORDER BY [t].[LastName], [t].[FirstName] DESC, [t].[Id] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class MappingExtensions | |
{ | |
public static IQueryable<Index.Model> MapCollectionTo(this IQueryable<Customer> customers) | |
{ | |
return customers.Select(customer => new Index.Model | |
{ | |
Id = customer.Id, | |
Email = customer.Email, | |
FirstName = customer.FirstName, | |
LastName = customer.LastName, | |
Schools = customer.CustomerSchools.Select(x => new Tuple<string, Guid>(x.School.Name, x.School.Id)).ToArray() | |
}); | |
} | |
} | |
/// <summary> | |
/// Provides named configuration for maps. | |
/// </summary> | |
public class MappingProfile : Profile | |
{ | |
/// <summary> | |
/// Initializes a new instance of the <see cref="MappingProfile"/> class. | |
/// </summary> | |
public MappingProfile() | |
{ | |
this.CreateMap<Customer, Index.Model>().ConvertUsing(source => Map(source)); | |
} | |
/// <summary> | |
/// Maps the <see cref="Customer"/> to an <see cref="Index.Model"/>. | |
/// </summary> | |
/// <param name="customer">The customer.</param> | |
/// <returns>The <see cref="Index.Model"/>.</returns> | |
public static Index.Model Map(Customer customer) | |
{ | |
return new Index.Model | |
{ | |
Id = customer.Id, | |
Email = customer.Email, | |
FirstName = customer.FirstName, | |
LastName = customer.LastName, | |
Schools = customer.CustomerSchools.Select(x => new Tuple<string, Guid>(x.School.Name, x.School.Id)) | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Interesting things to note.
ProjectTo<T>(IQueryable)
selects extra propertiesToArray()
call is removed, EF Core will generate an additional SQL query for each school in theIQueryable
extension method, withProjectTo
the SQL remains the sameIt would be nice if I could figure out a way to avoid multiple queries but EF Core does this by design for navigation properties in 2.x