Whilst not making the app source code public, there are now two apps that demonstrate the Entity Framework Core functionality as used in the app. One a Blazor Server (only) and the other a port of that to a Blazor Wasm app.


The app is for helpers to volunteer for assistance tasks at a track meet. Entity Framework Core is used with the main entities being Round, Helper and Activity. A Helper volunteers and performs an Activity at a Meet (called a Round).


The app functionality has been discussed in detail here Blazor Helpers App. The djaus2/BlazorEFBasics app was used to present some of this functionality, which IS available as above in GiThub. This app has now been extended to explore further issues. It now has been ported to djaus2/EFBlazorBasics_Wasm which is a PWA version of the app. Both app demonstrate functionality such as:

  • Entity Framework CRUD operations, using a SQL Server database.
  • Cascade Delete
  • Entity Tracking

They have both been published to Azure Static Websites and Azure SQL Database at:

The App pages

  • Home

  • Get sample data json
  • Get sample data entity

  • Setup Db
  • Get data from Db via a json string
    • http.GetAsync() then ..
    • JsonConvert.DeserializeObject()
  • Get data from Db direct
    • http.GetFromJsonAsync
  • Add Activity NoSave
  • Add Activity DbSave
  • Cascade Delete

  • Update - Copy Entity
  • Update - Submit Entity

The Razor page UI’s are essentially the same. The code behind is modified in for teh Wasm app using Http Get,Post,Put and Delete to a server Controller which calls the same (largely) database service as the Blazor Server only app. The service only app also has a page for updating an activity by forwarding the activity Id and updated property value only. I’m looking for the best way to do this via Http.

The apps facilitate the generation of fresh data as three interlocked entities directly from a json string which in setup is saved to the database as three tables after the tables are cleared and seeding is zeroed:

string ActivitysJson = "[{\"Round\":{\"No\":1},\"Helper\":{\"Name\":\"John Marshall\"}, \"Task\":\"Shot Put\"},{ \"Round\":{ \"No\":2},\"Helper\":{ \"Name\":\"Sue Burrows\"},\"Task\":\"Marshalling\"},{ \"Round\":{ \"No\":3},\"Helper\":{ \"Name\":\"Jimmy Beans\"},\"Task\":\"Discus\"}]";

Entity Change Tracking

Each DbContext instance tracks changes made to entities. These tracked entities in turn drive the changes to the database when SaveChanges is called. (See reference 1. below)

How to track entities

Entity instances become tracked when they are:

  • Returned from a query executed against the database
  • Explicitly attached to the DbContext by Add, Attach, Update, or similar methods
  • Detected as new entities connected to existing tracked entities
  • Entity instances are no longer tracked when:

The DbContext is disposed when:

  • The change tracker is cleared (EF Core 5.0 and later)
  • The entities are explicitly detached

DbContext is designed to represent a short-lived unit-of-work, as described in DbContext Initialization and Configuration. This means that disposing the DbContext is the normal way to stop tracking entities.
In other words, the lifetime of a DbContext should be:

  1. Create the DbContext instance
  2. Track some entities
  3. Make some changes to the entities
  4. Call SaveChanges to update the database
  5. Dispose the DbContext instance

Tip
It is not necessary to clear the change tracker or explicitly detach entity instances when taking this approach. However, if you do need to detach entities, then calling ChangeTracker.Clear is more efficient than detaching entities one-by-one.

The above is all a direct quotation from reference 1 (See below).

DbContext Lifetime

Also, as a quote from Microsoft Docs in “The DbContext lifetime” (See reference 2. below):

The lifetime of a DbContext begins when the instance is created and ends when the instance is disposed. A DbContext instance is designed to be used for a single unit-of-work. This means that the lifetime of a DbContext instance is usually very short.

A typical unit-of-work when using Entity Framework Core (EF Core) involves:

  • Creation of a DbContext instance
  • Tracking of entity instances by the context. Entities become tracked by
    • Being returned from a query
    • Being added or attached to the context Changes are made to the tracked entities as needed to implement the business rule
  • SaveChanges or SaveChangesAsync is called. EF Core detects the changes made and writes them to the database.
  • The DbContext instance is disposed

Important

It is very important to dispose the DbContext after use. This ensures both that any unmanaged resources are freed, and that any events or other hooks are unregistered so as to prevent memory leaks in case the instance remains referenced.

App Settings

To explorer context tracking, with both of the apps, a some global settings that can be toggled:

  • Enable/Disable calling database Context.SaveChanges() after entity modifications. (Default: enabled)
  • Enable/Disable setting Context.Entry(Entity).State = EntityState.Modified after entity modifications. (Default: Disabled)

  • Also, with the Wasm app there is an a option to Enable/Disable Null Activity Helpers Before Deleting a Helper (Default: Enabled)

Referential Actions

With respect to the third setting, the apps are set for Cascade deletion such as when a round is deleted, any activity for that round is deleted as a round is Required property for an activity. The Helper property of an activity is nullable as its not required (it isn’t necessarily assigned when a an activity is created). Deletion of a Helper needs to nullify its entry in an assigned activity. This works automatically as configured, in the server only app. With the same database configuration in the Wasm app, it was found that you do need to explicitly delete all activities of a helper before deleting the helper.

    public class Activity
    {
        [Key]
        [Column("Id")]
        public int Id { get; set; }

        [Column("Round")]
        [Required]
        public Round Round { get; set; }

        [Column("Helper")]
        public Helper Helper { get; set; }

        [Column("Task")]
        [Required]
        public string Task { get; set; }

    }

The Activity Class Note that the property Round is Required. Helper can be null

    constraints: table =>
    {
        table.PrimaryKey("PK_Activitys", x => x.Id);
        table.ForeignKey(
            name: "FK_Activitys_Helpers_HelperId",
            column: x => x.HelperId,
            principalTable: "Helpers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
        table.ForeignKey(
            name: "FK_Activitys_Rounds_RoundId",
            column: x => x.RoundId,
            principalTable: "Rounds",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
    });

The EF database constraints for Activitys Note the different constraints for Round and Helper entities.

  1. Entity Change Tracking

  2. The DbContext lifetime

  3. ReferentialAction Enums


 TopicSubtopic
<  Prev:   Blazor Helpers App Twilio
   
 This Category Links 
Category:Blazor Index:Blazor
  Next: > Blazor Helpers App
<  Prev:   Blazor Helpers App