Entity Framework error: The field X is required

ef-code-first entity-framework entity-framework-6

Question

I have the following class:

public class Foo
{
        [Key] 
        public int ID { get; set; }

        [Required]
        [StringLength(100)]
        public string Name { get; set; }

        [Required]
        public float Quantity { get; set; } 
}

and I'm using the following code to update the property Quantity:

  Foo f = new Foo {ID = 2, Quantity = 10}; // Updated object  

  DbSet dbSet = this.Set(f.GetType());
  dbSet.Attach(f);
  var be = Entry(f);
  be.Property("Quantity").IsModified = true;

  DBContext.SaveChanges();

However, the code produces an exception like this:

"The field 'Name' is required"

As far as I know the last piece of code should only update the field Quantity but it is taking into account the field Name as well.

I could avoid this error by taking the object before the update

Foo f = DBContext.Foos.Single<Foo>( x => x.ID == 2);
f.Quantity = 10; 
DBContext.SaveChanges();

but I think that is not a good option because it will spend two database accesses.

Any suggestions will be appreciated.

1
3
9/2/2016 6:04:38 PM

Accepted Answer

Your code is ok. The only problem is the EF validation process that checks all properties (also the unchanged properties). So, if you set Name, EF will generate a query without Name in SET clause.

I mean, if you run this code

Foo f = new Foo {ID = 2, Quantity = 10, Name = "Don't care"}; // Updated object  

DbSet dbSet = this.Set(f.GetType());
dbSet.Attach(f);
var be = Entry(f);
be.Property("Quantity").IsModified = true;

DBContext.SaveChanges();

EF will run this query

update [Foos]
set [Quantity] = @p0
where ([ID] = @p1)

@p0 = 10
@p1 = 2
2
9/2/2016 9:12:19 PM

Popular Answer

Option 1

As others have indicated, you could create a stub entity with dummy values for its required properties. However, you seem to have several classes having a Quantity property that you want to update this way. It would be quite a hassle to have to know all required properties of these classes.

I think a better option is to turn off validation altogether, by adding one line:

DBContext.Configuration.ValidateOnSaveEnabled = false;

just before DBContext.SaveChanges();.

I assume you use a context briefly, as recommended, so it won't be necessary to turn validation on again.

Not validating Quantity is safe. It's a non-nullable float so you can't ever set a null value for it inadvertently. But note that when you require other validations [Required], for example a maximum value, you'd have to add these explicitly.

Option 2

A more advanced alternative is to override the context's ShouldValidateEntity method, by making it skip entities having only one modified property named "Quantity":

protected override bool ShouldValidateEntity(DbEntityEntry entityEntry)
{
    if (entityEntry.State == System.Data.Entity.EntityState.Modified)
    {
        var ose = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager
                     .GetObjectStateEntry(entityEntry.Entity);
        var modifiedProperties = ose.GetModifiedProperties();
        var isValidated = modifiedProperties.Count() == 1 
                       && modifiedProperties.Any(p => p == "Quantity");
        return !isValidated;
    }
    return base.ShouldValidateEntity(entityEntry);
}

If you want, you can make this behavior switchable as well, for example by adding some boolean property to your context.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow