Given this extremely simple model:
public class MyContext : BaseContext
{
public DbSet<Foo> Foos { get; set; }
public DbSet<Bar> Bars { get; set; }
}
public class Foo
{
public int Id { get; set; }
public int Data { get; set; }
[Required]
public virtual Bar Bar { get; set; }
}
public class Bar
{
public int Id { get; set; }
}
The following program fails:
object id;
using (var context = new MyContext())
{
var foo = new Foo { Bar = new Bar() };
context.Foos.Add(foo);
context.SaveChanges();
id = foo.Id;
}
using (var context = new MyContext())
{
var foo = context.Foos.Find(id);
foo.Data = 2;
context.SaveChanges(); //Crash here
}
With a DbEntityValidationException
. The message found in EntityValidationErrors
is The Bar field is required..
However, if I force loading of the Bar
property by adding the following line before SaveChanges
:
var bar = foo.Bar;
Everything works fine. This also works if I remove the [Required]
attribute.
Is this really the expected behavior? Are there any workarounds (besides loading every single required reference every time I want to update an entity)
If anyone wants a general approach to solve this problem, here you have a custom DbContext which finds out properties based on these constraints:
virtual
ValidationAttribute
attribute.After retrieving this list, on any
SaveChanges
in which have something to modify it will load all references and collections automatically avoiding any unexpected exception.Where
IEntity<T>
is:These extensions were used in this code:
Hope it helps,
Since this is still a problem in EF 6.1.1 I thought I would provide another answer that may suit some people, depending on their exact model requirements. To summarize the issue:
You need to use a proxy for lazy loading.
The property you are lazy loading is marked Required.
You want to modify and save the proxy without having to force-load the lazy references.
3 is not possible with the current EF proxies (either of them), which is a serious shortcoming in my opinion.
In my case the lazy property behaves like a value type so its value is provided when we add the entity and never changed. I can enforce this by making its setter protected and not providing a method to update it, that is, it must be created through a constructor, eg:
MyEntity has this property:
So EF will not perform validation on this property but I can ensure it is not null in the constructor. That is one scenario.
Assuming you do not want to use the constructor in that way, you can still ensure validation using a custom attribute, such as:
The RequiredForAdd attribute is a custom attribute that inherits from Attribute not RequiredAttribute. It has no properties or methods apart from its base ones.
In my DB Context class I have a static constructor which finds all the properties with those attributes:
Now that we have a list of properties we need to check manually, we can override validation and manually validate them, adding any errors to the collection returned from the base validator:
Note that I am only interested in validating for an Add; if you wanted to check during Modify as well, you would need to either do the force-load for the property or use a Sql command to check the foreign key value (shouldn't that already be somewhere in the context)?
Because the Required attribute has been removed, EF will create a nullable FK; to ensure you DB integrity you could alter the FKs manually in a Sql script that you run against your database after it has been created. This will at least catch the Modify with null issues.