EF Core: Difference between revisions
(Created page with "<strong>Update entity classes</strong> by running the below command in PowerShell. Server 10.0.2.6 is QA database. Change the database (e.g. below is using MrDairyNovus as an example). <pre>dotnet ef dbcontext scaffold "Server=10.0.2.6;Database=MrDairyNovus;User Id=novususer;Password=h55C*ZftMX1V#ZWZ;" Microsoft.EntityFrameworkCore.SqlServer --startup-project "Novus.Web" --project "Novus.Model.Entity" -f --context-dir "..\Novus.DataAccess" -c NOVUSContext -o "Entities"<...") |
(No difference)
|
Latest revision as of 12:21, 4 October 2023
Update entity classes by running the below command in PowerShell. Server 10.0.2.6 is QA database. Change the database (e.g. below is using MrDairyNovus as an example).
dotnet ef dbcontext scaffold "Server=10.0.2.6;Database=MrDairyNovus;User Id=novususer;Password=h55C*ZftMX1V#ZWZ;" Microsoft.EntityFrameworkCore.SqlServer --startup-project "Novus.Web" --project "Novus.Model.Entity" -f --context-dir "..\Novus.DataAccess" -c NOVUSContext -o "Entities"
Update entity classes (for Shell database). Change the database (e.g. below is using MrDairyShell as an example).
dotnet ef dbcontext scaffold "Server=10.0.2.6;Database=MrDairyShell; User Id=novususer;Password=h55C*ZftMX1V#ZWZ;" Microsoft.EntityFrameworkCore.SqlServer --startup-project "Novus.Web" --project "Shell.Model.Entity" -f --context-dir "..\Shell.DataAccess" -c ShellContext -o "Entities"
Update entity classes (for Identity database). Run this inside the IdentityServer project. Each environment (QA, UAT, or production) has only one Identity database. This database is rarely updated.
dotnet ef dbcontext scaffold "Server=10.0.2.6;Database=Identity; User Id=novususer;Password=h55C*ZftMX1V#ZWZ;" Microsoft.EntityFrameworkCore.SqlServer -f --context-dir "DataAccess" -c AppDbContext -o "Entities"
After running scaffold command, copy the Novus.DataAccess/NOVUSContext.cs file and relevant entity class files in the Novus.Model.Entity/Entities folder into a temporary folder, run git restore Novus.DataAccess/NOVUSContext.cs to reset the DbContext class, run git restore Novus.Model.Entity/Entities to reset the entity classes, and run git clean -f Novus.Model.Entity/Entities to clear out any new entities.
In the temporary folder, if it is a new entity, copy the whole entity class file into Novus.Model.Entity/Entities folder, otherwise if it is an existing entity, just copy changes into existing entity class; open NOVUSContext.cs in a text editor, locate the auto-generated fluent API configuration for the relevant entities, if it is a new entity, copy the fluent API code (the code inside the lambda function passed into modelBuilder.Entity<Foo>()), in Visual Studio right-click Novus.DataAccess/EntityConfig folder > New Item, select C# class, name the class <entity>Config.cs, click Add, make class extend interface and paste the fluent API config into the method:
public class FooConfig : IEntityTypeConfiguration<Foo> { public void Configure(EntityTypeBuilder<Foo> entity) { entity.HasKey(e => e.FooKey); entity.ToTable("Foo"); // properties ... } }
Apply configuration in Novus.DataAccess/EntityConfig/DbContextExtensions.cs e.g. modelBuilder.ApplyConfiguration(new FooConfig()), otherwise if it is existing entity, just copy changes into existing config and entity class file(s).
Custom fluent API configuration. To enforce UTC date time on a property before EF Core saves the entity, in the fluent API configuration add UsesUtc(). For example, many entities implement the AuditFields interface which have the CreatedOn and UpdatedOn properties which should be in UTC date and time. If the entity have row versioning, (see Optimistic Concurrency Control section), add IsConcurrencyToken(). The reason to create IEntityTypeConfiguration config files is to ensure the scaffold command does not override the entity fluent API configuration, because the scaffold command auto-generates the DbContext overriding any custom configuration.
Custom modifications to entity class. The scaffold command auto-generates entity classes overriding any custom moficiations to the entity class. To solve this, create a partial class in Novus.Model.Entity/PartialEntities folder with same namespace as real entity class inside Novus.Model.Entity/Entities:
namespace Novus.Model.Entity.Entities { public partial class Foo { // properties ... } }
If the entity has created_by, updated_on, etc. fields, implement AuditFields in the class inside the PartialEntities folder, If the entity has version field, implement OptimisticConcurrencyControl in the class inside the PartialEntities folder.
You must fix the NOVUSContext class's namespace back to Novus.DataAccess and import the entities namespace with using Novus.Model.Entity.Entities. To prevent client-side evaluation, add the following logger in NOVUSContext:
public static readonly LoggerFactory _myLoggerFactory = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() });
And then in the OnConfiguring() method, add the following lines:
optionsBuilder.UseLoggerFactory(_myLoggerFactory);
Unfortunately, there's too much code by other developers which consists of EF Core queries which rely on client-side evaluation. I tried helping a developer to refactor a query that used a LINQ Count() by adding a grouping statement but didn't work. The logger is not commented out since it can log the generated SQL statements.
For the most part, Visfuture follows the database first approach instead of the code first approach (i.e. we do not use EF Core migrations feature).
Try-catch block: TODO
Return to Programming Guide