When utilizing lazy-loaded, needed properties, validation fails on update in EF.

ef-code-first entity-framework

Question

Given this really basic 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 software shown below 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 aDbEntityValidationException . Message included inEntityValidationErrors is 23-zzz-zzzz.

But if I force the loading of theBar property by adding the following line beforeSaveChanges :

var bar = foo.Bar;

It all works properly. Additionally, if I take out the[Required] attribute.

Is this conduct truly what we should expect? Are there any alternatives? (besides loading every single required reference every time I want to update an entity)

1
69
5/18/2011 12:52:40 AM

Accepted Answer

I discovered the following article, which offered a solution to the similar issue:

The cause of this problem is that in RC and RTM validation no longer lazy loads any properties. The reason this change was made is because when saving a lot of entities at once that have lazy loaded properties validation would get them one by one potentially causing a lot of unexpected transactions and crippling performance.

The workaround is to explicitly load all validated properties before saving or validating by using .Include(), you can read more on how to do this here: http://blogs.msdn.com/b/adonet/archive/2011/01/31/using-dbcontext-in-ef-feature-ctp5-part-6-loading-related-entities.aspx

This is a rather bad proxy implementation, in my opinion. You shouldn't need to go un-proxying a wrapper to confirm that it exists, even if it is obviously best to avoid traversing the object graph and retrieving lazy-loaded attributes (although this was apparently ignored in Microsoft's original version of EF). On second thinking, I'm not sure why you need to traverse the object graph in the first place; the ORM's change tracker must already be aware of which objects need to be validated.

I'm not sure why the issue arises, but I'm certain that it wouldn't exist if I were using, let's say, NHibernate.

My "workaround" is defining the relationship's Required status in an EntityTypeConfiguration class and eliminating the Required property. It should function properly as a result. It implies that you won't verify the relationship but that the update will fail. Not the best outcome.

54
10/13/2012 6:54:09 AM

Popular Answer

Okay, here is the actual response.

Initially, a brief explanation

If you own property (such as yourBar ) seeing an FK (ForeignKey ), you can also include the appropriate FK field in your model if we just want the FK rather than the actual data.Bar It doesn't have to be added to the database:

[ForeignKey("BarId")]
public virtual Bar Bar { get; set; }
public int BarId { get; set; }

Now that I've addressed your inquiry, what can you do toBar Required will flag theBarId the necessary attribute, but not theBar itself:

[ForeignKey("BarId")]
public virtual Bar Bar { get; set; }
[Required] //this makes the trick
public int BarId { get; set; }

This is a miracle worker.



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