导航 属性 为空 Entity Framework
Navigation property null with Entity Framework
我使用 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));
});
}
}
}
和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));
}
}
};
}
}
当我第一次创建这些对象时它工作正常(因为我明确设置了导航属性然后保存):
但是,当我关闭所有内容并从数据库中获取这些内容时:
导航属性未解析。 table 定义很好地设置了外键关系:
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 table 中的 ID 匹配。
我的存储库中有这个集合:
context.Configuration.ProxyCreationEnabled = true;
context.Configuration.LazyLoadingEnabled = true;
并且在我尝试解决此问题时上下文仍然处于活动状态 属性。
一切正常,但我在使用 EF 时多次遇到此问题,我的导航属性只是 运行domly 中断。我不记得接触过与此元素关联的任何代码,只是 运行 它现在不起作用。有人可以帮忙吗?
编辑:这是存储库代码:
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 的帮助下在评论中找到了答案。
问题在于拥有私有构造函数:
// Parameterless constructor for serialization
private Element() { }
proxies 的要求之一是 public 或受保护的构造函数:
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.
我使用 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));
});
}
}
}
和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));
}
}
};
}
}
当我第一次创建这些对象时它工作正常(因为我明确设置了导航属性然后保存):
但是,当我关闭所有内容并从数据库中获取这些内容时:
导航属性未解析。 table 定义很好地设置了外键关系:
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 table 中的 ID 匹配。
我的存储库中有这个集合:
context.Configuration.ProxyCreationEnabled = true;
context.Configuration.LazyLoadingEnabled = true;
并且在我尝试解决此问题时上下文仍然处于活动状态 属性。
一切正常,但我在使用 EF 时多次遇到此问题,我的导航属性只是 运行domly 中断。我不记得接触过与此元素关联的任何代码,只是 运行 它现在不起作用。有人可以帮忙吗?
编辑:这是存储库代码:
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 的帮助下在评论中找到了答案。
问题在于拥有私有构造函数:
// Parameterless constructor for serialization
private Element() { }
proxies 的要求之一是 public 或受保护的构造函数:
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.