我首先使用带有代码的 Entity Framework 。我的关系属性不断中断。
我有对象 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));
});
}
}
}
和元素类型
:
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));
}
}
};
}
}
当我第一次创建这些对象时它工作正常(因为我明确设置了导航属性然后保存):
但是,当我关闭所有内容并从数据库中获取这些内容时:
导航属性未解析。表定义很好地设置了外键关系:
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);
我可以看到数据都是正确的:
ID Name ElementType_ID
ff186746-62cb-4246-9c64-f2d007b23ac0 Aircon Test 27/03/2017 12:54:03 57d93ac1-ad3b-4718-a593-80639cc24907
与 ElementType 表中的 ID 匹配。
我的存储库中有这个集合:
context.Configuration.ProxyCreationEnabled = true;
context.Configuration.LazyLoadingEnabled = true;
并且在我尝试解析此属性时上下文仍然处于事件状态。
一切正常,但我在使用 EF 时多次遇到这个问题,我的导航属性只是随机中断。我不记得接触过与此元素关联的任何代码,只是运行它,但现在它不起作用。谁能帮忙?
编辑:这是存储库代码:
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;
}
...
}
上下文像这样存储它们:
public class DataContext : DbContext
{
...
public DbSet<Element> Elements { get; set; }
public DbSet<ElementType> ElementTypes { get; set; }
}
我认为这与访问有关。我正在使用 context.Set().Find(id) 作为 T 访问元素,但它失败了。但是,如果我浏览 ElementTypes,找到它的实体列表,那么它工作正常。
最佳答案
在 Ivan 的帮助下在评论中找到了答案。
问题在于拥有私有(private)构造函数:
// Parameterless constructor for serialization
private Element() { }
proxies 的要求之一是公共(public)或 protected 构造函数:
For either of these proxies to be created: A custom data class must be declared with public access.
A custom data class must not be sealed (NotInheritable in Visual Basic)
A custom data class must not be abstract (MustInherit in Visual Basic).
A custom data class must have a public or protected constructor that does not have parameters. Use a protected constructor without parameters if you want the CreateObject method to be used to create a proxy for the POCO entity. Calling the CreateObject method does not guarantee the creation of the proxy: the POCO class must follow the other requirements that are described in this topic.
The class cannot implement the IEntityWithChangeTracker or IEntityWithRelationships interfaces because the proxy classes implement these interfaces.
The ProxyCreationEnabled option must be set to true.
For lazy loading proxies: Each navigation property must be declared as public, virtual (Overridable in Visual Basic), and not sealed (NotOverridable in Visual Basic) get accessor.
关于c# - Entity Framework 的导航属性为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43045908/