Entity Update including the need, or not, to do an EntityStste update before SaveChanges().

When a logged in user “volunteers” for an Activity, the Helper property of the Activity, which would be null, is set to that user.

    // in HelperService
    public async Task AssignHelper(Activity activity, Helper helper, Helper assignee)
    {
        activity.Helper = helper;
        if (assignee == null)
            activity.Helper = helper;
        else
            activity.Helper = assignee; ;
        activity.DateAssigned = DateTime.Now.Date;
        _context.Entry(activity).State = EntityState.Modified;
        await _context.SaveChangesAsync();
    }

The person actioning the volunteer is normally the Helper who is volunteered. But to assist, an Admin user can assign, and deassign anyone in eth list of Helpers. So if a query is made such, “Who volunteered me for that?” a check can be made. Note also, that to keep control Helpers can’t deassign themselves. They have to make a request to an Admin.

At a database level, it is the Id of the Helper and the Id of the assignee tha is stored, but this is made transparent to the C# code by Entity Framework and the DBContext .

The following is a variant of the code above. It essentially checks th athe Activity is in the database before modifying it.

    // in HelperService
    public async Task AssignHelper(Activity activity, Helper helper, Helper assignee)
    {
        var allList = await _context.Activitys.ToListAsync();
        var activitys = from l in allList where l.Id == activity.Id select l;
        var activity2 = activitys.FirstOrDefault();
        if (activity2==null)
            return;
        activity2.Helper = helper;
        if (assignee == null)
            activity2.Helper = helper;
        else
            activity2.Helper = assignee; ;
        _context.Entry(activity2).State = EntityState.Modified;
        await _context.SaveChangesAsync();
    }

Could also check that the Helper and assignee exist in the database but that would be overkill as only a logged in Helper or Admin would be actioning this. But generally it is a good idea to check for the existence of a databse record before trying to update it.

A much simpler update without any checks and balances follows:

    public async Task UpdateHelper(Helper helper)
    {
        _context.Helpers.Update(helper);
        await _context.SaveChangesAsync();
    }

This just assumes the Helper with helper.Id exists and is being tracked by the DBContext and so will have its properties, except Id set to those for helper.

The question though is when should the EntityState for the DbContext be set prior to
context.SaveChanges()? eg:

_context.Entry(activity2).State = EntityState.Modified;

Reference: EnityState Enum in Microsoft Dox

One reply on StackOverFlow here is:
“It is required if your changes in the entity was done when entity was not tracked by EF context (the entity was detached). If you load entity from the context, modify it and save it by the same context you don’t need to use it because EF will track changes and set the state automatically.”
I Have also posted a similar query on StackOverflow here

My interpretation is that if the entity has been loaded via the DbContext then it is tracked through modification. Hence:

  • Context selections are not modifiactions so nothingto see here.
  • Any context entity addition would be tracked.
  • Any deletion via Id where the entity is fteched from the context via its Id would be tracked.
  • Similarly, update via Id where the entity is feteched from the context via its Id and midified would be tracked.

An “incontext” entity deletion:

    public async Task RemoveActivity(int Id)
    {
        var allList = await _context.Activitys.Include(activity => activity.Helper).Include(activity => activity.Round).ToListAsync();
        var subList = from l in allList where l.Id == Id select l;
        Activity activity = subList.FirstOrDefault();
        if (activity != null)
        {
            _context.Remove(activity);
            await _context.SaveChangesAsync();
        }
    }

An “incontext” entity update (the first method in this post minus the .state line):

    // in HelperService
    public async Task AssignHelper(Activity activity, Helper helper, Helper assignee)
    {
        var allList = await _context.Activitys.ToListAsync();
        var activitys = from l in allList where l.Id == activity.Id select l;
        var activity2 = activitys.FirstOrDefault();
        if (activity2==null)
            return;
        activity2.Helper = helper;
        if (assignee == null)
            activity2.Helper = helper;
        else
            activity2.Helper = assignee; ;
        await _context.SaveChangesAsync();
    }

activityId, like with the, deletion would have been a suitable parameter for the above method.

Further, reading the first reply to my StackOverflow query, the issue is about passing complete entity as a json string to a client browser and then passing that back modified as json string, deserializing it and submitting it directly as an update. Accepting such string and submitting it is rather insecure. The Helper App, being a Blazor Server app, does not pass entities to a client. It sends rendered data and receives form data.

Note that using the entity Id to query for it also checks that it exists.


 TopicSubtopic
  Next: > Azure Devops Jekyll Site
   
 This Category Links 
Category:Blazor Index:Blazor
  Next: > Blazor Helpers App
<  Prev:   Blazor Helpers App