WebApi + ClientApp, GraphQL, Reflection
This commit is contained in:
143
ReflectionBenchmark/Events.EF/Data/MSSQL/EventsContext.cs
Normal file
143
ReflectionBenchmark/Events.EF/Data/MSSQL/EventsContext.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Events.EF.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Events.EF.Data.MSSQL;
|
||||
|
||||
public partial class EventsContext : DbContext
|
||||
{
|
||||
public EventsContext(DbContextOptions<EventsContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual DbSet<Country> Countries { get; set; }
|
||||
|
||||
public virtual DbSet<Event> Events { get; set; }
|
||||
|
||||
public virtual DbSet<Person> People { get; set; }
|
||||
|
||||
public virtual DbSet<Registration> Registrations { get; set; }
|
||||
|
||||
public virtual DbSet<Sport> Sports { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Country>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Code);
|
||||
|
||||
entity.ToTable("Country");
|
||||
|
||||
entity.HasIndex(e => e.Name, "UQ_Country_Name").IsUnique();
|
||||
|
||||
entity.Property(e => e.Code)
|
||||
.HasMaxLength(3)
|
||||
.IsUnicode(false);
|
||||
entity.Property(e => e.Alpha3)
|
||||
.HasMaxLength(3)
|
||||
.IsUnicode(false)
|
||||
.IsFixedLength();
|
||||
entity.Property(e => e.Name)
|
||||
.HasMaxLength(100)
|
||||
.IsUnicode(false);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Event>(entity =>
|
||||
{
|
||||
entity.ToTable("Event");
|
||||
|
||||
entity.Property(e => e.Name)
|
||||
.HasMaxLength(150)
|
||||
.IsUnicode(false);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Person>(entity =>
|
||||
{
|
||||
entity.ToTable("Person");
|
||||
|
||||
entity.HasIndex(e => new { e.DocumentNumber, e.CountryCode }, "UQ_Person_DocumentNumber_CountryCode").IsUnique();
|
||||
|
||||
entity.Property(e => e.AddressCountry)
|
||||
.HasMaxLength(100)
|
||||
.IsUnicode(false);
|
||||
entity.Property(e => e.AddressLine)
|
||||
.HasMaxLength(200)
|
||||
.IsUnicode(false);
|
||||
entity.Property(e => e.City)
|
||||
.HasMaxLength(100)
|
||||
.IsUnicode(false);
|
||||
entity.Property(e => e.ContactPhone)
|
||||
.HasMaxLength(50)
|
||||
.IsUnicode(false);
|
||||
entity.Property(e => e.CountryCode)
|
||||
.HasMaxLength(3)
|
||||
.IsUnicode(false);
|
||||
entity.Property(e => e.DocumentNumber)
|
||||
.HasMaxLength(50)
|
||||
.IsUnicode(false);
|
||||
entity.Property(e => e.Email)
|
||||
.HasMaxLength(255)
|
||||
.IsUnicode(false);
|
||||
entity.Property(e => e.FirstName)
|
||||
.HasMaxLength(100)
|
||||
.IsUnicode(false);
|
||||
entity.Property(e => e.FirstNameTranscription)
|
||||
.HasMaxLength(100)
|
||||
.IsUnicode(false);
|
||||
entity.Property(e => e.LastName)
|
||||
.HasMaxLength(100)
|
||||
.IsUnicode(false);
|
||||
entity.Property(e => e.LastNameTranscription)
|
||||
.HasMaxLength(100)
|
||||
.IsUnicode(false);
|
||||
entity.Property(e => e.PostalCode)
|
||||
.HasMaxLength(20)
|
||||
.IsUnicode(false);
|
||||
|
||||
entity.HasOne(d => d.CountryCodeNavigation).WithMany(p => p.People)
|
||||
.HasForeignKey(d => d.CountryCode)
|
||||
.OnDelete(DeleteBehavior.ClientSetNull)
|
||||
.HasConstraintName("FK_Person_Country");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Registration>(entity =>
|
||||
{
|
||||
entity.ToTable("Registration");
|
||||
|
||||
entity.HasIndex(e => new { e.PersonId, e.SportId, e.EventId }, "UQ_Registration_PersonId_SportId_EventId").IsUnique();
|
||||
|
||||
entity.Property(e => e.RegisteredAt).HasDefaultValueSql("(sysutcdatetime())", "DF_Registration_RegisteredAt");
|
||||
|
||||
entity.HasOne(d => d.Event).WithMany(p => p.Registrations)
|
||||
.HasForeignKey(d => d.EventId)
|
||||
.HasConstraintName("FK_Registration_Event");
|
||||
|
||||
entity.HasOne(d => d.Person).WithMany(p => p.Registrations)
|
||||
.HasForeignKey(d => d.PersonId)
|
||||
.HasConstraintName("FK_Registration_Person");
|
||||
|
||||
entity.HasOne(d => d.Sport).WithMany(p => p.Registrations)
|
||||
.HasForeignKey(d => d.SportId)
|
||||
.HasConstraintName("FK_Registration_Sport");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Sport>(entity =>
|
||||
{
|
||||
entity.ToTable("Sport");
|
||||
|
||||
entity.HasIndex(e => e.Name, "UQ_Sport_Name").IsUnique();
|
||||
|
||||
entity.Property(e => e.Name)
|
||||
.HasMaxLength(100)
|
||||
.IsUnicode(false);
|
||||
});
|
||||
|
||||
OnModelCreatingPartial(modelBuilder);
|
||||
}
|
||||
|
||||
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||
}
|
||||
165
ReflectionBenchmark/Events.EF/Data/Postgres/EventsContext.cs
Normal file
165
ReflectionBenchmark/Events.EF/Data/Postgres/EventsContext.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Events.EF.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Events.EF.Data.Postgres;
|
||||
|
||||
public partial class EventsContext : DbContext
|
||||
{
|
||||
public EventsContext(DbContextOptions<EventsContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual DbSet<Country> Countries { get; set; }
|
||||
|
||||
public virtual DbSet<Event> Events { get; set; }
|
||||
|
||||
public virtual DbSet<Person> People { get; set; }
|
||||
|
||||
public virtual DbSet<Registration> Registrations { get; set; }
|
||||
|
||||
public virtual DbSet<Sport> Sports { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Country>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Code).HasName("country_pkey");
|
||||
|
||||
entity.ToTable("country");
|
||||
|
||||
entity.HasIndex(e => e.Name, "country_name_key").IsUnique();
|
||||
|
||||
entity.Property(e => e.Code)
|
||||
.HasMaxLength(3)
|
||||
.HasColumnName("code");
|
||||
entity.Property(e => e.Alpha3)
|
||||
.HasMaxLength(3)
|
||||
.IsFixedLength()
|
||||
.HasColumnName("alpha3");
|
||||
entity.Property(e => e.Name)
|
||||
.HasMaxLength(100)
|
||||
.HasColumnName("name");
|
||||
entity.Property(e => e.Translations)
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("translations");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Event>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("event_pkey");
|
||||
|
||||
entity.ToTable("event");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.EventDate).HasColumnName("event_date");
|
||||
entity.Property(e => e.Name)
|
||||
.HasMaxLength(150)
|
||||
.HasColumnName("name");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Person>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("person_pkey");
|
||||
|
||||
entity.ToTable("person");
|
||||
|
||||
entity.HasIndex(e => new { e.DocumentNumber, e.CountryCode }, "person_document_number_country_code_key").IsUnique();
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.AddressCountry)
|
||||
.HasMaxLength(100)
|
||||
.HasColumnName("address_country");
|
||||
entity.Property(e => e.AddressLine)
|
||||
.HasMaxLength(200)
|
||||
.HasColumnName("address_line");
|
||||
entity.Property(e => e.BirthDate).HasColumnName("birth_date");
|
||||
entity.Property(e => e.City)
|
||||
.HasMaxLength(100)
|
||||
.HasColumnName("city");
|
||||
entity.Property(e => e.ContactPhone)
|
||||
.HasMaxLength(50)
|
||||
.HasColumnName("contact_phone");
|
||||
entity.Property(e => e.CountryCode)
|
||||
.HasMaxLength(3)
|
||||
.HasColumnName("country_code");
|
||||
entity.Property(e => e.DocumentNumber)
|
||||
.HasMaxLength(50)
|
||||
.HasColumnName("document_number");
|
||||
entity.Property(e => e.Email)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("email");
|
||||
entity.Property(e => e.FirstName)
|
||||
.HasMaxLength(100)
|
||||
.HasColumnName("first_name");
|
||||
entity.Property(e => e.FirstNameTranscription)
|
||||
.HasMaxLength(100)
|
||||
.HasColumnName("first_name_transcription");
|
||||
entity.Property(e => e.LastName)
|
||||
.HasMaxLength(100)
|
||||
.HasColumnName("last_name");
|
||||
entity.Property(e => e.LastNameTranscription)
|
||||
.HasMaxLength(100)
|
||||
.HasColumnName("last_name_transcription");
|
||||
entity.Property(e => e.PostalCode)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("postal_code");
|
||||
|
||||
entity.HasOne(d => d.CountryCodeNavigation).WithMany(p => p.People)
|
||||
.HasForeignKey(d => d.CountryCode)
|
||||
.OnDelete(DeleteBehavior.ClientSetNull)
|
||||
.HasConstraintName("person_country_code_fkey");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Registration>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("registration_pkey");
|
||||
|
||||
entity.ToTable("registration");
|
||||
|
||||
entity.HasIndex(e => new { e.PersonId, e.SportId, e.EventId }, "registration_person_id_sport_id_event_id_key").IsUnique();
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.EventId).HasColumnName("event_id");
|
||||
entity.Property(e => e.PersonId).HasColumnName("person_id");
|
||||
entity.Property(e => e.RegisteredAt)
|
||||
.HasDefaultValueSql("CURRENT_TIMESTAMP")
|
||||
.HasColumnName("registered_at");
|
||||
entity.Property(e => e.SportId).HasColumnName("sport_id");
|
||||
|
||||
entity.HasOne(d => d.Event).WithMany(p => p.Registrations)
|
||||
.HasForeignKey(d => d.EventId)
|
||||
.HasConstraintName("registration_event_id_fkey");
|
||||
|
||||
entity.HasOne(d => d.Person).WithMany(p => p.Registrations)
|
||||
.HasForeignKey(d => d.PersonId)
|
||||
.HasConstraintName("registration_person_id_fkey");
|
||||
|
||||
entity.HasOne(d => d.Sport).WithMany(p => p.Registrations)
|
||||
.HasForeignKey(d => d.SportId)
|
||||
.HasConstraintName("registration_sport_id_fkey");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Sport>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("sport_pkey");
|
||||
|
||||
entity.ToTable("sport");
|
||||
|
||||
entity.HasIndex(e => e.Name, "sport_name_key").IsUnique();
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.Name)
|
||||
.HasMaxLength(100)
|
||||
.HasColumnName("name");
|
||||
});
|
||||
|
||||
OnModelCreatingPartial(modelBuilder);
|
||||
}
|
||||
|
||||
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||
}
|
||||
14
ReflectionBenchmark/Events.EF/Events.EF.csproj
Normal file
14
ReflectionBenchmark/Events.EF/Events.EF.csproj
Normal file
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.7" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
19
ReflectionBenchmark/Events.EF/Models/Country.cs
Normal file
19
ReflectionBenchmark/Events.EF/Models/Country.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Events.EF.Models;
|
||||
|
||||
public partial class Country
|
||||
{
|
||||
public string Code { get; set; } = null!;
|
||||
|
||||
public string Alpha3 { get; set; } = null!;
|
||||
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
public string? Translations { get; set; }
|
||||
|
||||
public virtual ICollection<Person> People { get; set; } = new List<Person>();
|
||||
}
|
||||
17
ReflectionBenchmark/Events.EF/Models/Event.cs
Normal file
17
ReflectionBenchmark/Events.EF/Models/Event.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Events.EF.Models;
|
||||
|
||||
public partial class Event
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
public DateOnly EventDate { get; set; }
|
||||
|
||||
public virtual ICollection<Registration> Registrations { get; set; } = new List<Registration>();
|
||||
}
|
||||
41
ReflectionBenchmark/Events.EF/Models/Person.cs
Normal file
41
ReflectionBenchmark/Events.EF/Models/Person.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Events.EF.Models;
|
||||
|
||||
public partial class Person
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string? FirstName { get; set; }
|
||||
|
||||
public string? LastName { get; set; }
|
||||
|
||||
public string FirstNameTranscription { get; set; } = null!;
|
||||
|
||||
public string LastNameTranscription { get; set; } = null!;
|
||||
|
||||
public string? AddressLine { get; set; }
|
||||
|
||||
public string? PostalCode { get; set; }
|
||||
|
||||
public string? City { get; set; }
|
||||
|
||||
public string? AddressCountry { get; set; }
|
||||
|
||||
public string? Email { get; set; }
|
||||
|
||||
public string? ContactPhone { get; set; }
|
||||
|
||||
public DateOnly BirthDate { get; set; }
|
||||
|
||||
public string DocumentNumber { get; set; } = null!;
|
||||
|
||||
public string CountryCode { get; set; } = null!;
|
||||
|
||||
public virtual Country CountryCodeNavigation { get; set; } = null!;
|
||||
|
||||
public virtual ICollection<Registration> Registrations { get; set; } = new List<Registration>();
|
||||
}
|
||||
25
ReflectionBenchmark/Events.EF/Models/Registration.cs
Normal file
25
ReflectionBenchmark/Events.EF/Models/Registration.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Events.EF.Models;
|
||||
|
||||
public partial class Registration
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int PersonId { get; set; }
|
||||
|
||||
public int SportId { get; set; }
|
||||
|
||||
public int EventId { get; set; }
|
||||
|
||||
public DateTime RegisteredAt { get; set; }
|
||||
|
||||
public virtual Event Event { get; set; } = null!;
|
||||
|
||||
public virtual Person Person { get; set; } = null!;
|
||||
|
||||
public virtual Sport Sport { get; set; } = null!;
|
||||
}
|
||||
15
ReflectionBenchmark/Events.EF/Models/Sport.cs
Normal file
15
ReflectionBenchmark/Events.EF/Models/Sport.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Events.EF.Models;
|
||||
|
||||
public partial class Sport
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
public virtual ICollection<Registration> Registrations { get; set; } = new List<Registration>();
|
||||
}
|
||||
70
ReflectionBenchmark/Events.EF/efpt.mssql.config.json
Normal file
70
ReflectionBenchmark/Events.EF/efpt.mssql.config.json
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"CodeGenerationMode": 6,
|
||||
"ContextClassName": "EventsContext",
|
||||
"ContextNamespace": null,
|
||||
"FilterSchemas": false,
|
||||
"IncludeConnectionString": false,
|
||||
"IrregularWords": null,
|
||||
"MinimumProductVersion": "2.6.1465",
|
||||
"ModelNamespace": null,
|
||||
"OutputContextPath": "Data\/MSSQL",
|
||||
"OutputPath": "Models",
|
||||
"PluralRules": null,
|
||||
"PreserveCasingWithRegex": true,
|
||||
"ProjectRootNamespace": "Events.EF",
|
||||
"Schemas": null,
|
||||
"SelectedHandlebarsLanguage": 2,
|
||||
"SelectedToBeGenerated": 0,
|
||||
"SingularRules": null,
|
||||
"T4TemplatePath": null,
|
||||
"Tables": [
|
||||
{
|
||||
"Name": "[dbo].[Country]",
|
||||
"ObjectType": 0
|
||||
},
|
||||
{
|
||||
"Name": "[dbo].[Event]",
|
||||
"ObjectType": 0
|
||||
},
|
||||
{
|
||||
"Name": "[dbo].[Person]",
|
||||
"ObjectType": 0
|
||||
},
|
||||
{
|
||||
"Name": "[dbo].[Registration]",
|
||||
"ObjectType": 0
|
||||
},
|
||||
{
|
||||
"Name": "[dbo].[Sport]",
|
||||
"ObjectType": 0
|
||||
}
|
||||
],
|
||||
"UiHint": null,
|
||||
"UncountableWords": null,
|
||||
"UseAsyncStoredProcedureCalls": true,
|
||||
"UseBoolPropertiesWithoutDefaultSql": false,
|
||||
"UseDatabaseNames": false,
|
||||
"UseDatabaseNamesForRoutines": true,
|
||||
"UseDateOnlyTimeOnly": true,
|
||||
"UseDbContextSplitting": false,
|
||||
"UseDecimalDataAnnotationForSprocResult": true,
|
||||
"UseFluentApiOnly": true,
|
||||
"UseHandleBars": false,
|
||||
"UseHierarchyId": false,
|
||||
"UseInflector": true,
|
||||
"UseInternalAccessModifiersForSprocsAndFunctions": false,
|
||||
"UseLegacyPluralizer": false,
|
||||
"UseManyToManyEntity": false,
|
||||
"UseNoDefaultConstructor": true,
|
||||
"UseNoNavigations": false,
|
||||
"UseNoObjectFilter": false,
|
||||
"UseNodaTime": false,
|
||||
"UseNullableReferences": true,
|
||||
"UsePrefixNavigationNaming": false,
|
||||
"UseSchemaFolders": false,
|
||||
"UseSchemaNamespaces": false,
|
||||
"UseSpatial": false,
|
||||
"UseT4": false,
|
||||
"UseT4Split": false,
|
||||
"UseTypedTvpParameters": true
|
||||
}
|
||||
70
ReflectionBenchmark/Events.EF/efpt.postgres.config.json
Normal file
70
ReflectionBenchmark/Events.EF/efpt.postgres.config.json
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"CodeGenerationMode": 6,
|
||||
"ContextClassName": "EventsContext",
|
||||
"ContextNamespace": null,
|
||||
"FilterSchemas": false,
|
||||
"IncludeConnectionString": false,
|
||||
"IrregularWords": null,
|
||||
"MinimumProductVersion": "2.6.1465",
|
||||
"ModelNamespace": null,
|
||||
"OutputContextPath": "Data\/Postgres",
|
||||
"OutputPath": "Models",
|
||||
"PluralRules": null,
|
||||
"PreserveCasingWithRegex": true,
|
||||
"ProjectRootNamespace": "Events.EF",
|
||||
"Schemas": null,
|
||||
"SelectedHandlebarsLanguage": 2,
|
||||
"SelectedToBeGenerated": 0,
|
||||
"SingularRules": null,
|
||||
"T4TemplatePath": null,
|
||||
"Tables": [
|
||||
{
|
||||
"Name": "public.country",
|
||||
"ObjectType": 0
|
||||
},
|
||||
{
|
||||
"Name": "public.event",
|
||||
"ObjectType": 0
|
||||
},
|
||||
{
|
||||
"Name": "public.person",
|
||||
"ObjectType": 0
|
||||
},
|
||||
{
|
||||
"Name": "public.registration",
|
||||
"ObjectType": 0
|
||||
},
|
||||
{
|
||||
"Name": "public.sport",
|
||||
"ObjectType": 0
|
||||
}
|
||||
],
|
||||
"UiHint": null,
|
||||
"UncountableWords": null,
|
||||
"UseAsyncStoredProcedureCalls": true,
|
||||
"UseBoolPropertiesWithoutDefaultSql": false,
|
||||
"UseDatabaseNames": false,
|
||||
"UseDatabaseNamesForRoutines": true,
|
||||
"UseDateOnlyTimeOnly": true,
|
||||
"UseDbContextSplitting": false,
|
||||
"UseDecimalDataAnnotationForSprocResult": true,
|
||||
"UseFluentApiOnly": true,
|
||||
"UseHandleBars": false,
|
||||
"UseHierarchyId": false,
|
||||
"UseInflector": true,
|
||||
"UseInternalAccessModifiersForSprocsAndFunctions": false,
|
||||
"UseLegacyPluralizer": false,
|
||||
"UseManyToManyEntity": false,
|
||||
"UseNoDefaultConstructor": true,
|
||||
"UseNoNavigations": false,
|
||||
"UseNoObjectFilter": false,
|
||||
"UseNodaTime": false,
|
||||
"UseNullableReferences": true,
|
||||
"UsePrefixNavigationNaming": false,
|
||||
"UseSchemaFolders": false,
|
||||
"UseSchemaNamespaces": false,
|
||||
"UseSpatial": false,
|
||||
"UseT4": false,
|
||||
"UseT4Split": false,
|
||||
"UseTypedTvpParameters": true
|
||||
}
|
||||
4
ReflectionBenchmark/ReflectionBenchmark.slnx
Normal file
4
ReflectionBenchmark/ReflectionBenchmark.slnx
Normal file
@@ -0,0 +1,4 @@
|
||||
<Solution>
|
||||
<Project Path="Events.EF/Events.EF.csproj" />
|
||||
<Project Path="ReflectionBenchmark/ReflectionBenchmark.csproj" />
|
||||
</Solution>
|
||||
45
ReflectionBenchmark/ReflectionBenchmark/CompiledMapper.cs
Normal file
45
ReflectionBenchmark/ReflectionBenchmark/CompiledMapper.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ReflectionBenchmark;
|
||||
|
||||
public static class CompiledMapper
|
||||
{
|
||||
public static Func<TSource, TDest> Create<TSource, TDest>()
|
||||
where TDest : new()
|
||||
{
|
||||
var sourceParam = Expression.Parameter(typeof(TSource), "src");
|
||||
|
||||
var sourceProps = typeof(TSource)
|
||||
.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
|
||||
var destProps = typeof(TDest)
|
||||
.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
|
||||
var bindings = new List<MemberBinding>();
|
||||
|
||||
foreach (var destProp in destProps)
|
||||
{
|
||||
var sourceProp = sourceProps
|
||||
.FirstOrDefault(p => p.Name == destProp.Name &&
|
||||
p.PropertyType == destProp.PropertyType);
|
||||
|
||||
if (sourceProp == null)
|
||||
continue;
|
||||
|
||||
var sourceAccess = Expression.Property(sourceParam, sourceProp);
|
||||
|
||||
var bind = Expression.Bind(destProp, sourceAccess);
|
||||
|
||||
bindings.Add(bind);
|
||||
}
|
||||
|
||||
var newDest = Expression.New(typeof(TDest));
|
||||
|
||||
var body = Expression.MemberInit(newDest, bindings);
|
||||
|
||||
var lambda = Expression.Lambda<Func<TSource, TDest>>(body, sourceParam);
|
||||
|
||||
return lambda.Compile();
|
||||
}
|
||||
}
|
||||
124
ReflectionBenchmark/ReflectionBenchmark/DBAccess.cs
Normal file
124
ReflectionBenchmark/ReflectionBenchmark/DBAccess.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using AutoMapper;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Events.EF.Data.Postgres;
|
||||
using Events.EF.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Npgsql;
|
||||
|
||||
namespace ReflectionBenchmark;
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public class DBAccess
|
||||
{
|
||||
IMapper mapper = null!;
|
||||
IHost host = null!;
|
||||
IDbContextFactory<EventsContext> dbContextFactory = null!;
|
||||
string connectionString = string.Empty;
|
||||
|
||||
[Params(1, 10, 1000, 10000)]
|
||||
public int Top { get; set; }
|
||||
|
||||
[GlobalSetup]
|
||||
public void PrepareMappings()
|
||||
{
|
||||
host = DISetup.BuildHost([]);
|
||||
dbContextFactory = host.Services.GetRequiredService<IDbContextFactory<EventsContext>>();
|
||||
|
||||
var config = new MapperConfiguration(cfg => cfg.CreateMap<Person, PersonDest>()
|
||||
.ForMember(d => d.FirstName,
|
||||
opt => opt.MapFrom(e => e.FirstNameTranscription))
|
||||
.ForMember(d => d.LastName,
|
||||
opt => opt.MapFrom(e => e.LastNameTranscription))
|
||||
.ForMember(d => d.Country,
|
||||
opt => opt.MapFrom(e => e.CountryCodeNavigation.Name)),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
mapper = new Mapper(config);
|
||||
connectionString = host.Services.GetRequiredService<IConfiguration>().GetConnectionString("EventsPostgres")
|
||||
?? throw new InvalidOperationException("Missing connection string 'EventsPostgres'.");
|
||||
}
|
||||
|
||||
[GlobalCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
host.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load top Top people ordered by last name, and then first name
|
||||
/// storing them in PersonDest manually
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Benchmark]
|
||||
public List<PersonDest> MapManually()
|
||||
{
|
||||
using var ctx = dbContextFactory.CreateDbContext();
|
||||
var query = ctx.People
|
||||
.OrderBy(p => p.LastNameTranscription)
|
||||
.ThenBy(p => p.FirstNameTranscription)
|
||||
.Take(Top)
|
||||
.Select(p => new PersonDest
|
||||
{
|
||||
FirstName = p.FirstNameTranscription,
|
||||
LastName = p.LastNameTranscription,
|
||||
Country = p.CountryCodeNavigation.Name
|
||||
});
|
||||
|
||||
var list = query.ToList();
|
||||
return list;
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public List<PersonDest> AdoNet()
|
||||
{
|
||||
List<PersonDest> list = new();
|
||||
using var connection = new NpgsqlConnection(connectionString);
|
||||
using var command = connection.CreateCommand();
|
||||
command.CommandText = """
|
||||
SELECT person.first_name_transcription, person.last_name_transcription, country.name
|
||||
FROM person
|
||||
INNER JOIN country ON country.code = person.country_code
|
||||
ORDER BY person.last_name_transcription, person.first_name_transcription
|
||||
LIMIT @top
|
||||
""";
|
||||
command.CommandType = System.Data.CommandType.Text;
|
||||
command.Parameters.AddWithValue("top", Top);
|
||||
connection.Open();
|
||||
using var reader = command.ExecuteReader();
|
||||
while(reader.Read())
|
||||
{
|
||||
list.Add(new PersonDest
|
||||
{
|
||||
FirstName = reader.GetString(0),
|
||||
LastName = reader.GetString(1),
|
||||
Country = reader.GetString(2)
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load top Top people ordered by last name, and then first name
|
||||
/// storing them in PersonDest using AutoMapper
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Benchmark]
|
||||
public List<PersonDest> MapAutoMapper()
|
||||
{
|
||||
using var ctx = dbContextFactory.CreateDbContext();
|
||||
var query = ctx.People
|
||||
.OrderBy(p => p.LastNameTranscription)
|
||||
.ThenBy(p => p.FirstNameTranscription)
|
||||
.Take(Top);
|
||||
|
||||
IQueryable<PersonDest> projectedQuery = mapper.ProjectTo<PersonDest>(query);
|
||||
|
||||
var list = projectedQuery.ToList();
|
||||
return list;
|
||||
}
|
||||
}
|
||||
21
ReflectionBenchmark/ReflectionBenchmark/DISetup.cs
Normal file
21
ReflectionBenchmark/ReflectionBenchmark/DISetup.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
using Events.EF.Data.Postgres;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace ReflectionBenchmark;
|
||||
|
||||
internal static class DISetup
|
||||
{
|
||||
public static IHost BuildHost(string[] args)
|
||||
{
|
||||
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
|
||||
|
||||
builder.Services.AddDbContextFactory<EventsContext>(options => {
|
||||
options.UseNpgsql(builder.Configuration.GetConnectionString("EventsPostgres"));
|
||||
});
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
||||
9
ReflectionBenchmark/ReflectionBenchmark/PersonDest.cs
Normal file
9
ReflectionBenchmark/ReflectionBenchmark/PersonDest.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace ReflectionBenchmark;
|
||||
|
||||
public record PersonDest
|
||||
{
|
||||
public string FirstName { get; set; } = string.Empty;
|
||||
public string LastName { get; set; } = string.Empty;
|
||||
public string Country { get; set; } = string.Empty;
|
||||
public DateTime Birthday { get; set; }
|
||||
}
|
||||
9
ReflectionBenchmark/ReflectionBenchmark/PersonSource.cs
Normal file
9
ReflectionBenchmark/ReflectionBenchmark/PersonSource.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace ReflectionBenchmark;
|
||||
|
||||
public class PersonSource
|
||||
{
|
||||
public string FirstName { get; set; } = string.Empty;
|
||||
public string LastName { get; set; } = string.Empty;
|
||||
public string Country { get; set; } = string.Empty;
|
||||
public DateTime Birthday { get; set; }
|
||||
}
|
||||
202
ReflectionBenchmark/ReflectionBenchmark/PersonUtil.cs
Normal file
202
ReflectionBenchmark/ReflectionBenchmark/PersonUtil.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
using System.Reflection;
|
||||
using AutoMapper;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Bogus;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
|
||||
|
||||
namespace ReflectionBenchmark;
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public class PersonUtil
|
||||
{
|
||||
Mapper mapper = null!;
|
||||
Faker<PersonSource> faker = null!;
|
||||
List<PersonSource> source = null!;
|
||||
public record Pair<T, U>(T DestProp, U SourceProp);
|
||||
static List<Pair<PropertyInfo, PropertyInfo>> mapping = new();
|
||||
static Dictionary<string, Func<PersonSource, object>> getters = new();
|
||||
static Dictionary<string, Action<PersonDest, object>> setters = new();
|
||||
static Func<PersonSource, PersonDest> compiledMapper = null!;
|
||||
|
||||
public record AccessPair(
|
||||
Func<PersonSource, object> Getter,
|
||||
Action<PersonDest, object> Setter);
|
||||
static List<AccessPair> accessorMapping = new();
|
||||
|
||||
[Params(1000)]
|
||||
public int ListSize { get; set; }
|
||||
|
||||
[GlobalSetup]
|
||||
public void PrepareMappingsAndData()
|
||||
{
|
||||
var config = new MapperConfiguration(cfg => cfg.CreateMap<PersonSource, PersonDest>(),
|
||||
NullLoggerFactory.Instance);
|
||||
mapper = new Mapper(config);
|
||||
|
||||
faker = new Faker<PersonSource>()
|
||||
.RuleFor(p => p.FirstName, f => f.Name.FirstName())
|
||||
.RuleFor(p => p.LastName, f => f.Name.LastName())
|
||||
.RuleFor(p => p.Country, f => f.Address.Country())
|
||||
.RuleFor(p => p.Birthday, f => f.Date.Between(new DateTime(1900), DateTime.Now));
|
||||
|
||||
source = faker.Generate(ListSize);
|
||||
|
||||
Type sourceType = typeof(PersonSource);
|
||||
if (getters.Count == 0)
|
||||
{
|
||||
getters = PropertyAccessorCache.CreateAccessors<PersonSource>();
|
||||
|
||||
setters = PropertyAccessorCache.CreateSetters<PersonDest>();
|
||||
Type destType = typeof(PersonDest);
|
||||
|
||||
PropertyInfo[] sourceProperties = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
PropertyInfo[] destProperties = destType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
foreach (PropertyInfo destProperty in destProperties)
|
||||
{
|
||||
PropertyInfo? sourceProperty = sourceProperties.FirstOrDefault(d => d.Name == destProperty.Name);
|
||||
if (sourceProperty != null)
|
||||
{
|
||||
mapping.Add(new Pair<PropertyInfo, PropertyInfo>(destProperty, sourceProperty));
|
||||
}
|
||||
|
||||
if (getters.TryGetValue(destProperty.Name, out var getter) &&
|
||||
setters.TryGetValue(destProperty.Name, out var setter))
|
||||
{
|
||||
accessorMapping.Add(new AccessPair(getter, setter));
|
||||
}
|
||||
}
|
||||
compiledMapper = CompiledMapper.Create<PersonSource, PersonDest>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy source list to destination list converting each object to an object of another type
|
||||
/// "Conversion" is done line by line in foreach loop
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Benchmark]
|
||||
public List<PersonDest> MapForeach()
|
||||
{
|
||||
List<PersonDest> dest = new List<PersonDest>(source.Count);
|
||||
foreach (var item in source)
|
||||
{
|
||||
dest.Add(new PersonDest
|
||||
{
|
||||
FirstName = item.FirstName,
|
||||
LastName = item.LastName,
|
||||
Country = item.Country,
|
||||
Birthday = item.Birthday
|
||||
});
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public List<PersonDest> MapFor()
|
||||
{
|
||||
List<PersonDest> dest = new List<PersonDest>(source.Count);
|
||||
for (int i = 0; i < source.Count; i++)
|
||||
{
|
||||
PersonSource item = source[i];
|
||||
dest.Add(new PersonDest
|
||||
{
|
||||
FirstName = item.FirstName,
|
||||
LastName = item.LastName,
|
||||
Country = item.Country,
|
||||
Birthday = item.Birthday
|
||||
});
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy source list to destination list converting each object to an object of another type
|
||||
/// It is done using Linq instead of foreach loop
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Benchmark]
|
||||
public List<PersonDest> MapLinq()
|
||||
{
|
||||
return source.Select(s => new PersonDest
|
||||
{
|
||||
FirstName = s.FirstName,
|
||||
LastName = s.LastName,
|
||||
Country = s.Country,
|
||||
Birthday = s.Birthday
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy source list to destination list converting each object to an object of another type
|
||||
/// "Conversion" is done using reflection, where mapping is established in each test iteration
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Benchmark]
|
||||
public List<PersonDest> MapWithReflection()
|
||||
{
|
||||
List<PersonDest> dest = new List<PersonDest>(source.Count);
|
||||
|
||||
foreach (var sourceItem in source)
|
||||
{
|
||||
PersonDest personDest = new ();
|
||||
foreach (var pair in mapping)
|
||||
{
|
||||
pair.DestProp.SetValue(personDest, pair.SourceProp.GetValue(sourceItem));
|
||||
}
|
||||
dest.Add(personDest);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy source list to destination list converting each object to an object of another type
|
||||
/// "Conversion" is done using reflection, where mapping is established in each test iteration
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Benchmark]
|
||||
public List<PersonDest> WithPropertyAccessor()
|
||||
{
|
||||
List<PersonDest> dest = new List<PersonDest>(source.Count);
|
||||
|
||||
foreach (var sourceItem in source)
|
||||
{
|
||||
PersonDest personDest = new();
|
||||
foreach (var pair in accessorMapping)
|
||||
{
|
||||
pair.Setter(personDest, pair.Getter(sourceItem));
|
||||
}
|
||||
dest.Add(personDest);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public List<PersonDest> MapWithCompiledExpression()
|
||||
{
|
||||
List<PersonDest> dest = new(source.Count);
|
||||
|
||||
foreach (var item in source)
|
||||
{
|
||||
dest.Add(compiledMapper(item));
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy source list to destination list converting each object to an object of another type
|
||||
/// "Conversion" is done with AutoMapper (library made for this purpose)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Benchmark]
|
||||
public List<PersonDest> MapWithAutoMapper()
|
||||
{
|
||||
List<PersonDest> dest = new List<PersonDest>(source.Count);
|
||||
foreach (var item in source)
|
||||
{
|
||||
dest.Add(mapper.Map<PersonDest>(item));
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
7
ReflectionBenchmark/ReflectionBenchmark/Program.cs
Normal file
7
ReflectionBenchmark/ReflectionBenchmark/Program.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
// See https://aka.ms/new-console-template for more information
|
||||
using BenchmarkDotNet.Running;
|
||||
using ReflectionBenchmark;
|
||||
|
||||
var summary = BenchmarkRunner.Run<PersonUtil>();
|
||||
//var summary = BenchmarkRunner.Run<DBAccess>();
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ReflectionBenchmark;
|
||||
public class PropertyAccessorCache
|
||||
{
|
||||
|
||||
public static Dictionary<string, Func<T, object>> CreateAccessors<T>()
|
||||
{
|
||||
var dict = new Dictionary<string, Func<T, object>>();
|
||||
|
||||
foreach (var prop in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public))
|
||||
{
|
||||
if (!prop.CanRead) continue;
|
||||
|
||||
var param = Expression.Parameter(typeof(T));
|
||||
|
||||
var property = Expression.Property(param, prop);
|
||||
var convert = Expression.Convert(property, typeof(object));
|
||||
|
||||
var lambda = Expression.Lambda<Func<T, object>>(convert, param).Compile();
|
||||
|
||||
dict[prop.Name] = lambda;
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
public static Dictionary<string, Action<T, object>> CreateSetters<T>()
|
||||
{
|
||||
var dict = new Dictionary<string, Action<T, object>>();
|
||||
|
||||
foreach (var prop in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public))
|
||||
{
|
||||
if (!prop.CanWrite) continue;
|
||||
|
||||
var instanceParam = Expression.Parameter(typeof(T), "instance");
|
||||
var valueParam = Expression.Parameter(typeof(object), "value");
|
||||
|
||||
var property = Expression.Property(instanceParam, prop);
|
||||
|
||||
var valueCast = Expression.Convert(valueParam, prop.PropertyType);
|
||||
|
||||
var assign = Expression.Assign(property, valueCast);
|
||||
|
||||
var lambda = Expression
|
||||
.Lambda<Action<T, object>>(assign, instanceParam, valueParam)
|
||||
.Compile();
|
||||
|
||||
dict[prop.Name] = lambda;
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<UserSecretsId>PI</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="16.1.1" />
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.15.8" />
|
||||
<PackageReference Include="Bogus" Version="35.6.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.7" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Events.EF\Events.EF.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
13
ReflectionBenchmark/ReflectionBenchmark/appsettings.json
Normal file
13
ReflectionBenchmark/ReflectionBenchmark/appsettings.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"EventsPostgres": "Host=localhost;Port=5432;Database=events;Username=sport;Password=pogledaj u user secrets;Persist Security Info=True"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Error",
|
||||
"System": "Error",
|
||||
"Microsoft": "Error",
|
||||
"Microsoft.EntityFrameworkCore.Database.Command" : "Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
144
ReflectionBenchmark/ReflectionBenchmark/results.txt
Normal file
144
ReflectionBenchmark/ReflectionBenchmark/results.txt
Normal file
@@ -0,0 +1,144 @@
|
||||
BenchmarkDotNet=v0.13.3, OS=Windows 11 (10.0.22621.963)
|
||||
11th Gen Intel Core i7-1165G7 2.80GHz, 1 CPU, 8 logical and 4 physical cores
|
||||
.NET SDK=7.0.101
|
||||
[Host] : .NET 6.0.12 (6.0.1222.56807), X64 RyuJIT AVX2
|
||||
DefaultJob : .NET 6.0.12 (6.0.1222.56807), X64 RyuJIT AVX2
|
||||
|
||||
|
||||
| Method | ListSize | Mean | Error | StdDev | Ratio | RatioSD |
|
||||
|------------------ |--------- |-----------:|---------:|----------:|------:|--------:|
|
||||
| MapForeach | 10 | 108.5 ns | 2.17 ns | 2.50 ns | 1.00 | 0.00 |
|
||||
| MapLinq | 10 | 120.2 ns | 2.26 ns | 2.12 ns | 1.11 | 0.03 |
|
||||
| MapWithReflection | 10 | 4,818.1 ns | 95.43 ns | 194.94 ns | 45.30 | 2.68 |
|
||||
| MapWithAutoMapper | 10 | 546.3 ns | 10.90 ns | 12.12 ns | 5.04 | 0.15 |
|
||||
|
||||
|
||||
|
||||
BenchmarkDotNet v0.13.11, Windows 11 (10.0.22621.2861/22H2/2022Update/SunValley2)
|
||||
13th Gen Intel Core i5-1340P, 1 CPU, 16 logical and 12 physical cores
|
||||
.NET SDK 8.0.100
|
||||
[Host] : .NET 6.0.25 (6.0.2523.51912), X64 RyuJIT AVX2
|
||||
DefaultJob : .NET 6.0.25 (6.0.2523.51912), X64 RyuJIT AVX2
|
||||
|
||||
|
||||
| Method | ListSize | Mean | Error | StdDev | Ratio | RatioSD |
|
||||
|------------------ |--------- |------------:|----------:|---------:|------:|--------:|
|
||||
| MapForeach | 10 | 83.14 ns | 0.907 ns | 0.848 ns | 1.00 | 0.00 |
|
||||
| MapLinq | 10 | 117.53 ns | 1.680 ns | 1.571 ns | 1.41 | 0.03 |
|
||||
| MapWithReflection | 10 | 3,042.57 ns | 12.641 ns | 9.869 ns | 36.57 | 0.35 |
|
||||
| MapWithAutoMapper | 10 | 499.42 ns | 3.913 ns | 3.469 ns | 6.00 | 0.08 |
|
||||
|
||||
|
||||
BenchmarkDotNet v0.13.11, Windows 11 (10.0.22621.2861/22H2/2022Update/SunValley2)
|
||||
13th Gen Intel Core i5-1340P, 1 CPU, 16 logical and 12 physical cores
|
||||
.NET SDK 8.0.100
|
||||
[Host] : .NET 7.0.14 (7.0.1423.51910), X64 RyuJIT AVX2
|
||||
DefaultJob : .NET 7.0.14 (7.0.1423.51910), X64 RyuJIT AVX2
|
||||
|
||||
|
||||
| Method | ListSize | Mean | Error | StdDev | Ratio | RatioSD |
|
||||
|------------------ |--------- |------------:|----------:|---------:|------:|--------:|
|
||||
| MapForeach | 10 | 84.94 ns | 0.814 ns | 0.680 ns | 1.00 | 0.00 |
|
||||
| MapLinq | 10 | 111.17 ns | 2.226 ns | 2.286 ns | 1.31 | 0.03 |
|
||||
| MapWithReflection | 10 | 1,008.92 ns | 10.223 ns | 9.562 ns | 11.87 | 0.14 |
|
||||
| MapWithAutoMapper | 10 | 504.64 ns | 5.971 ns | 5.585 ns | 5.94 | 0.07 |
|
||||
|
||||
|
||||
|
||||
BenchmarkDotNet v0.13.11, Windows 11 (10.0.22621.2861/22H2/2022Update/SunValley2)
|
||||
13th Gen Intel Core i5-1340P, 1 CPU, 16 logical and 12 physical cores
|
||||
.NET SDK 8.0.100
|
||||
[Host] : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
|
||||
DefaultJob : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
|
||||
|
||||
|
||||
| Method | ListSize | Mean | Error | StdDev | Ratio | RatioSD |
|
||||
|------------------ |--------- |----------:|----------:|---------:|------:|--------:|
|
||||
| MapForeach | 10 | 80.67 ns | 0.663 ns | 0.554 ns | 1.00 | 0.00 |
|
||||
| MapLinq | 10 | 107.38 ns | 2.131 ns | 1.993 ns | 1.33 | 0.03 |
|
||||
| MapWithReflection | 10 | 668.54 ns | 10.255 ns | 9.593 ns | 8.30 | 0.14 |
|
||||
| MapWithAutoMapper | 10 | 424.24 ns | 6.710 ns | 5.603 ns | 5.26 | 0.08 |
|
||||
|
||||
|
||||
|
||||
BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4460/23H2/2023Update/SunValley3)
|
||||
13th Gen Intel Core i5-1340P, 1 CPU, 16 logical and 12 physical cores
|
||||
.NET SDK 8.0.404
|
||||
[Host] : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2
|
||||
DefaultJob : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2
|
||||
|
||||
|
||||
| Method | ListSize | Mean | Error | StdDev | Ratio | RatioSD |
|
||||
|------------------ |--------- |----------:|---------:|---------:|------:|--------:|
|
||||
| MapForeach | 10 | 78.10 ns | 0.764 ns | 0.715 ns | 1.00 | 0.01 |
|
||||
| MapLinq | 10 | 108.61 ns | 0.945 ns | 0.838 ns | 1.39 | 0.02 |
|
||||
| MapWithReflection | 10 | 641.86 ns | 6.721 ns | 6.287 ns | 8.22 | 0.11 |
|
||||
| MapWithAutoMapper | 10 | 418.63 ns | 2.366 ns | 2.098 ns | 5.36 | 0.05 |
|
||||
|
||||
|
||||
--------------------------
|
||||
Database in local container:
|
||||
|
||||
BenchmarkDotNet v0.13.11, Windows 11 (10.0.22621.2861/22H2/2022Update/SunValley2)
|
||||
13th Gen Intel Core i5-1340P, 1 CPU, 16 logical and 12 physical cores
|
||||
.NET SDK 8.0.100
|
||||
[Host] : .NET 6.0.25 (6.0.2523.51912), X64 RyuJIT AVX2
|
||||
DefaultJob : .NET 6.0.25 (6.0.2523.51912), X64 RyuJIT AVX2
|
||||
|
||||
|
||||
| Method | Top | Mean | Error | StdDev | Ratio | RatioSD |
|
||||
|-------------- |---- |---------:|----------:|----------:|------:|--------:|
|
||||
| MapManually | 10 | 3.391 ms | 0.2923 ms | 0.8527 ms | 1.00 | 0.00 |
|
||||
| MapAutoMapper | 10 | 3.223 ms | 0.3683 ms | 1.0801 ms | 1.00 | 0.39 |
|
||||
|
||||
|
||||
BenchmarkDotNet v0.13.11, Windows 11 (10.0.22621.2861/22H2/2022Update/SunValley2)
|
||||
13th Gen Intel Core i5-1340P, 1 CPU, 16 logical and 12 physical cores
|
||||
.NET SDK 8.0.100
|
||||
[Host] : .NET 7.0.14 (7.0.1423.51910), X64 RyuJIT AVX2
|
||||
DefaultJob : .NET 7.0.14 (7.0.1423.51910), X64 RyuJIT AVX2
|
||||
|
||||
|
||||
| Method | Top | Mean | Error | StdDev | Ratio | RatioSD |
|
||||
|-------------- |---- |---------:|----------:|----------:|------:|--------:|
|
||||
| MapManually | 10 | 3.283 ms | 0.3443 ms | 1.0044 ms | 1.00 | 0.00 |
|
||||
| MapAutoMapper | 10 | 2.824 ms | 0.3019 ms | 0.8757 ms | 0.95 | 0.43 |
|
||||
|
||||
BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4460/23H2/2023Update/SunValley3)
|
||||
13th Gen Intel Core i5-1340P, 1 CPU, 16 logical and 12 physical cores
|
||||
.NET SDK 8.0.404
|
||||
[Host] : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2
|
||||
DefaultJob : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2
|
||||
|
||||
|
||||
| Method | Top | Mean | Error | StdDev | Ratio | RatioSD |
|
||||
|-------------- |---- |---------:|----------:|----------:|------:|--------:|
|
||||
| MapManually | 10 | 1.143 ms | 0.0227 ms | 0.0651 ms | 1.00 | 0.08 |
|
||||
| MapAutoMapper | 10 | 1.077 ms | 0.0213 ms | 0.0351 ms | 0.95 | 0.06 |
|
||||
|
||||
|
||||
|
||||
BenchmarkDotNet v0.14.0, Windows 11 (10.0.26200.7171)
|
||||
13th Gen Intel Core i5-1340P, 1 CPU, 16 logical and 12 physical cores
|
||||
.NET SDK 9.0.308
|
||||
[Host] : .NET 8.0.22 (8.0.2225.52707), X64 RyuJIT AVX2
|
||||
DefaultJob : .NET 8.0.22 (8.0.2225.52707), X64 RyuJIT AVX2
|
||||
|
||||
|
||||
| Method | Top | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|
||||
|-------------- |------ |-----------:|---------:|----------:|-----------:|------:|--------:|--------:|-------:|----------:|------------:|
|
||||
| MapManually | 1 | 1,562.0 us | 89.21 us | 261.63 us | 1,530.7 us | 1.94 | 0.39 | 11.7188 | 3.9063 | 90.31 KB | 31.23 |
|
||||
| AdoNet | 1 | 818.2 us | 37.96 us | 103.93 us | 802.5 us | 1.01 | 0.17 | - | - | 2.89 KB | 1.00 |
|
||||
| MapAutoMapper | 1 | 1,258.5 us | 29.91 us | 82.87 us | 1,234.8 us | 1.56 | 0.20 | 13.6719 | 3.9063 | 88.38 KB | 30.57 |
|
||||
| | | | | | | | | | | | |
|
||||
| MapManually | 10 | 1,313.9 us | 48.35 us | 132.35 us | 1,294.8 us | 1.65 | 0.18 | 11.7188 | 3.9063 | 93.7 KB | 19.69 |
|
||||
| AdoNet | 10 | 796.4 us | 15.77 us | 39.57 us | 788.2 us | 1.00 | 0.07 | - | - | 4.76 KB | 1.00 |
|
||||
| MapAutoMapper | 10 | 1,335.9 us | 44.21 us | 122.50 us | 1,317.6 us | 1.68 | 0.17 | 11.7188 | 3.9063 | 92.04 KB | 19.34 |
|
||||
| | | | | | | | | | | | |
|
||||
| MapManually | 1000 | 1,750.7 us | 66.48 us | 186.41 us | 1,716.0 us | 1.27 | 0.15 | 23.4375 | 3.9063 | 157.96 KB | 4.15 |
|
||||
| AdoNet | 1000 | 1,387.4 us | 30.22 us | 82.72 us | 1,374.0 us | 1.00 | 0.08 | 5.8594 | - | 38.09 KB | 1.00 |
|
||||
| MapAutoMapper | 1000 | 1,746.5 us | 49.52 us | 134.71 us | 1,729.9 us | 1.26 | 0.12 | 23.4375 | 3.9063 | 156.25 KB | 4.10 |
|
||||
| | | | | | | | | | | | |
|
||||
| MapManually | 10000 | 1,750.1 us | 70.01 us | 198.61 us | 1,707.3 us | 1.28 | 0.17 | 23.4375 | 3.9063 | 157.95 KB | 4.15 |
|
||||
| AdoNet | 10000 | 1,374.6 us | 33.90 us | 95.63 us | 1,366.8 us | 1.00 | 0.10 | 5.8594 | - | 38.09 KB | 1.00 |
|
||||
| MapAutoMapper | 10000 | 1,736.7 us | 42.34 us | 116.63 us | 1,726.7 us | 1.27 | 0.12 | 23.4375 | 3.9063 | 156.24 KB | 4.10 |
|
||||
Reference in New Issue
Block a user