I'm using Entity Framework with Code first. My Relationship properties keep breaking.
I have the object Element:
public class Element : IElement
{
// ... some event handlers (removed)
[Key]
public Guid ID { get; set; } = Guid.NewGuid();
public string Name { get; set; }
// navigation properties
public virtual ElementType ElementType { get; private set; }
public virtual NotifiableCollection<Property> Properties { get; private set; } = new NotifiableCollection<Property>();
// Parameterless constructor for serialization
private Element() { }
public Element(ElementType elementType) : base()
{
// loop through and create Properties for each Property Type
ElementType = elementType;
if (ElementType?.PropertyTypes != null)
{
ElementType.PropertyTypes.ToList().ForEach((property) =>
{
Properties.Add(new Property(property));
});
}
}
}
And ElementType:
public class ElementType : IElementType
{
// ... some event handlers (removed)
[Key]
public Guid ID { get; set; } = Guid.NewGuid();
public string Name { get; set; }
// navigation properties
public virtual NotifiableCollection<PropertyType> PropertyTypes { get; set; } = new NotifiableCollection<PropertyType>();
public virtual NotifiableCollection<Element> Elements { get; set; } = new NotifiableCollection<Element>();
public ElementType()
{
// ensure our Element's get updates
PropertyTypes.CollectionChanged += (e, a) =>
{
//update the database to send out renewal to interested entities
if (a.ChangeType == ChangeType.Added)
{
foreach (Element element in Elements)
{
element.Properties.Add(new Property(a.Item));
}
}
};
}
}
It works fine when I create these objects the first time (as I've explicitly set the navigation properties then saved):
However, when I then close everything and get these from the database:
The navigation properties are not resolved. The table definitions set up the foregn key relationship fine:
CREATE TABLE [dbo].[Elements] (
[ID] UNIQUEIDENTIFIER NOT NULL,
[Name] NVARCHAR (MAX) NULL,
[ElementType_ID] UNIQUEIDENTIFIER NULL,
CONSTRAINT [PK_dbo.Elements] PRIMARY KEY CLUSTERED ([ID] ASC),
CONSTRAINT [FK_dbo.Elements_dbo.ElementTypes_ElementType_ID] FOREIGN KEY ([ElementType_ID]) REFERENCES [dbo].[ElementTypes] ([ID])
);
GO
CREATE NONCLUSTERED INDEX [IX_ElementType_ID]
ON [dbo].[Elements]([ElementType_ID] ASC);
and I can see the data is all correct:
ID Name ElementType_ID
ff186746-62cb-4246-9c64-f2d007b23ac0 Aircon Test 27/03/2017 12:54:03 57d93ac1-ad3b-4718-a593-80639cc24907
which matches an ID in ElementType table.
I have this set in my repository:
context.Configuration.ProxyCreationEnabled = true;
context.Configuration.LazyLoadingEnabled = true;
And the context is still active at the time where I'm trying to resolve this property.
Everything was working, but I've had this problem multiple times with EF, where my navigation properties just break randomly. I don't remember touching any of the code associated with this element, just ran it and now it doesn't work. Can anyone help?
Edit: This is the repository code:
public sealed class Repository : IRepository
{
public event ObjectMaterializedEventHandler ObjectMaterialized;
public Repository() {
(context as IObjectContextAdapter).ObjectContext.ObjectMaterialized += ObjectContext_ObjectMaterialized; ;
context.Configuration.ProxyCreationEnabled = true;
context.Configuration.LazyLoadingEnabled = true;
}
// I do this to wire in some events later
private void ObjectContext_ObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
{
ObjectMaterialized?.Invoke(this, e);
}
private DataContext context = new DataContext(false);
public IEnumerable<T> GetAll<T>() where T : class
{
return context.Set<T>().ToList() as IEnumerable<T>;
}
public T GetItem<T>(Guid id) where T : class
{
return context.Set<T>().Find(id) as T;
}
...
}
the context stores them like this:
public class DataContext : DbContext
{
...
public DbSet<Element> Elements { get; set; }
public DbSet<ElementType> ElementTypes { get; set; }
}
I think it IS something to do with accessing. I'm accessing the Element with context.Set().Find(id) as T, and it fails. However, if I navagate through the ElementTypes, find it's list of Entities, then it works fine.


usingblock perhaps?Findis not returning proxy. So either (A) for some reason theElementis not eligible for lazy loading to EF, or (B) you have added theElementinstance manually. If you put a breakpoint and trycontext.Set<Element>().Create();, does it return proxy (to eliminate the case (B))?