When updating Marking entity datetime property unc

2019-04-02 16:34发布

问题:

I have this entity service in my domain model with two datetime type properties entrydate and updatedon.

When user in edit view make any changes and submit form back I want entrydate property of the postedback/modified object to be marked as unchanged so entrydate can't be overwritten when performing updates.

public class Service
{
    public int ServiceID
    {
        get;
        set;

    }
    [Required(ErrorMessage="Please enter Name")]
    public string Name
    {
        get;
        set;
    }

    [Required(ErrorMessage="Please enter the duration for the service")]
    public short Duration
    {
        get;
        set;
    }


    [DataType(DataType.Date)]
    public DateTime EntryDate
    {
        get;
        set;
    }

    [DataType(DataType.Date)]
    public DateTime UpdatedOn
    {
        get;
        set;
    }



    public decimal Cost
    {
        get; set;

    }
}

Repository method that is persisting changes into db is as follows:

 public void InsertOrUpdate(Service service)
    {
        if (service.ServiceID == default(int)) {
            // New entity
            context.Services.Add(service);
        } else {
            // Existing entity

            context.Entry(service).State = EntityState.Modified;
        }
    }

回答1:

You can reload the original entity from the database:

else {
    // Existing entity
    var serviceInDb = context.Services.Find(service.ServiceID);
    service.EntryDate = serviceInDb.EntryDate;
    context.Entry(serviceInDb).CurrentValues.SetValues(service);
}

When you call SaveChanges later an UPDATE statement only for properties which have really changed will be sent to the database (has also benefits for other unchanged properties).

Or just reload the EntryDate:

else {
    // Existing entity
    var entryDateInDb = context.Services
        .Select(s => s.EntryDate)
        .Single(s => s.ServiceID == service.ServiceID);
    service.EntryDate = entryDateInDb;
    context.Entry(service).State = EntityState.Modified;
}

Another working but ugly approach is this:

context.Services.Attach(service); // thanks to user202448, see comments

context.Entry(service).Property(s => s.Name).IsModified = true;
context.Entry(service).Property(s => s.Duration).IsModified = true;
context.Entry(service).Property(s => s.UpdatedOn).IsModified = true;
context.Entry(service).Property(s => s.Cost).IsModified = true;

So, don't set the EntryDate property to modified but all the other properties one by one.

The approach which comes into mind ...

context.Entry(service).State = EntityState.Modified;
context.Entry(service).Property(s => s.EntryDate).IsModified = false;

... unfortunately doesn't work because setting back a property to not-modified which is already marked as Modified is not supported and will throw an exception.