Entity Framework 6 立即加载列表
Entity Framework 6 Load List on Eager Load
Entity Framework 正在加载 Polygon
中的所有内容,但我的 LineSegments
列表除外。我错过了什么?
多边形:
public class Polygon
{
List<LineSegment> _lineSegments = new List<LineSegment>();
public List<LineSegment> LineSegments
{
get { return _lineSegments; }
protected set { _lineSegments = value; }
}
public Point BasePoint { get; protected set; }
public Vector NormalVector { get; protected set; }
public int? DatabaseId { get; set; }
// ...
}
LineSegment class(Polygon
有这些的列表)
public class LineSegment
{
public virtual Distance Magnitude
{
get { return _magnitude; }
set { _magnitude = value; }
}
private Distance _magnitude;
public virtual Point BasePoint
{
get { return _basePoint; }
set { this._basePoint = value; }
}
private Point _basePoint;
public virtual Direction Direction
{
get { return _direction; }
set { _direction = value; }
}
private Direction _direction;
public int? DatabaseId { get; set; }
// ...
}
这是模型中的关系设置:
modelBuilder.Entity<Polygon>()
.HasMany(polygon => polygon.LineSegments);
因此,多边形和线段都有一个 table,它们会正确插入线段引用多边形的位置。但是当我尝试使用预先加载检索它们时,它不会加载列表。我在包含中列出了 LineSegment 的属性,但它不起作用。我想我需要修改模型中的关系设置,但我不确定如何修改。 如何更正此问题,以便在加载多边形时立即加载 LineSegments 列表?这是查询:
private static List<Expression<Func<Polygon, object>>> polygonRegionNaviationProperties = new List<Expression<Func<Polygon, object>>>()
{
(polygon => polygon.BasePoint),
(polygon => polygon.BasePoint.X),
(polygon => polygon.BasePoint.Y),
(polygon => polygon.BasePoint.Z),
(polygon => polygon.NormalVector),
(polygon => polygon.NormalVector.Direction),
(polygon => polygon.NormalVector.Direction.Phi),
(polygon => polygon.NormalVector.Direction.Theta),
(polygon => polygon.NormalVector.Magnitude),
(polygon => polygon.NormalVector.BasePoint.X),
(polygon => polygon.NormalVector.BasePoint.Y),
(polygon => polygon.NormalVector.BasePoint.Z),
(polygon => polygon.LineSegments),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.Direction)),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.Direction.Phi)),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.Direction.Theta)),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.Magnitude)),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.BasePoint.X)),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.BasePoint.Y)),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.BasePoint.Z))
};
public Polygon GetPolygon(int? databaseId)
{
if(databaseId != null)
{
Polygon retrievedPolygon = Query((polygon => polygon.DatabaseId == databaseId), polygonRegionNaviationProperties);
return retrievedPolygon;
}
else
{
return null;
}
}
public override Polygon Query(Expression<Func<Polygon, bool>> match, List<Expression<Func<Polygon, object>>> includes = null)
{
using (var databaseContext = new ClearspanDatabaseContext())
{
databaseContext.Database.Log = Console.Write;
if (includes != null)
{
var dataSet = databaseContext.Set<Polygon>(); // Get the relevant DataSet
Polygon retrievedObject = includes.Aggregate( // Eagerly load the passed navigation properties
dataSet.AsQueryable(),
(current, include) => current.Include(include)
).SingleOrDefault(match);
databaseContext.Entry(retrievedObject).Collection(polygon => polygon.LineSegments).Load();
return retrievedObject;
}
else
{
Polygon retrievedObject = databaseContext.Set<Polygon>().SingleOrDefault(match);
databaseContext.Entry(retrievedObject).Collection(polygon => polygon.LineSegments).Load();
return retrievedObject;
}
}
}
更新
这是一个 link 到一个细化的 project 来说明我的问题。
- 克隆它。
- 初始化子模块(项目根目录中的
git submodule init
和git submodule update
)(如果您使用SourceTree,这可能会自动发生)
- 运行 PostgreSQL 脚本,请注意您不能 运行 一次性完成所有操作,因为它正在创建数据库。关注顶部的评论。
- 运行 单元测试,请注意,除了 InsertAndRetrievePolygon 之外,它们都应该通过。那是因为没有检索到列表,您可以通过将鼠标悬停在调试器中的变量上来查看。
希望对理解、诊断和解决这个问题有所帮助。您会注意到,在我的问题中,我简化了 GeometryClassLibrary 中实际存在的层次结构。谢谢,斯科特 H
尝试按如下方式更改您的 class:
public class Polygon
{
public virtual List<LineSegment> LineSegments
{
get;
set;
}
// ...
}
在您的查询中,仅包含导航属性。不应包含字符串、原始类型和枚举类型。像这样:
var dataSet = databaseContext.Set<Polygon>();
Polygon retrievedObject = dataSet.Include(i => i.LineSegments).SingleOrDefault(match);
return retrievedObject;
这对你有用吗?
我将在此处查看有关 Code First 中一对多关系的第一个示例。
http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx
我认为 Fabio Luz 走在正确的轨道上。 LineSegments 集合应该是虚拟的。您还可以尝试覆盖默认构造函数并实例化 属性。另外,LineSegmentsclass中的Polygon大概应该有一个virtual属性来完成引用关系。
public class Polygon
{
public Polygon()
{
LineSegments = new List<LineSegment>();
}
public virtual List<LineSegment> LineSegments
{
get;
set;
}
// ...
}
public class LineSegment
{
public virtual Polygon Polygon { get; set; }
}
这是Polygon.LineSegments
的代码:
public virtual List<LineSegment> LineSegments
{
get { return this._Edges.Select(e => (LineSegment)e).ToList(); }
set { _Edges = value.ToList<IEdge>(); }
}
当 EF 填充子集合时,它不会为其分配 complete 集合,但会在必要时对其进行初始化,然后向其添加项目。现在陷阱来了:EF 将项目添加到哪个集合?不是 _Edges
,而是 ToList()
每次处理 LineSegments
时构建的临时集合。 _Edges
本身仍然是空的。
不幸的是,你不能通过 Include()
-ing Edges
代替 LineSegments
来解决这个问题,因为这是 Edges
的代码:
protected List<IEdge> _Edges = new List<IEdge>();
public virtual List<IEdge> Edges
{
get { return _Edges; }
set { _Edges = value; }
}
并且 EF 不支持接口。坦率地说,我不知道是否有合适的解决方法。 LineSegments
中的这种间接访问可能会导致更多 EF 问题。例如,我认为 关系修复 (从加载到上下文中的实体自动填充导航属性)也不会 运行。
我知道这些 类 来自外部图书馆。我看到所有这些 XyzEntityFramework
部分 类 那里(例如 LineSegmentEntityFramework
)似乎添加了属性以促进使用 EF。也许他们愿意查看您的问题并找到解决方案。
Entity Framework 正在加载 Polygon
中的所有内容,但我的 LineSegments
列表除外。我错过了什么?
多边形:
public class Polygon
{
List<LineSegment> _lineSegments = new List<LineSegment>();
public List<LineSegment> LineSegments
{
get { return _lineSegments; }
protected set { _lineSegments = value; }
}
public Point BasePoint { get; protected set; }
public Vector NormalVector { get; protected set; }
public int? DatabaseId { get; set; }
// ...
}
LineSegment class(Polygon
有这些的列表)
public class LineSegment
{
public virtual Distance Magnitude
{
get { return _magnitude; }
set { _magnitude = value; }
}
private Distance _magnitude;
public virtual Point BasePoint
{
get { return _basePoint; }
set { this._basePoint = value; }
}
private Point _basePoint;
public virtual Direction Direction
{
get { return _direction; }
set { _direction = value; }
}
private Direction _direction;
public int? DatabaseId { get; set; }
// ...
}
这是模型中的关系设置:
modelBuilder.Entity<Polygon>()
.HasMany(polygon => polygon.LineSegments);
因此,多边形和线段都有一个 table,它们会正确插入线段引用多边形的位置。但是当我尝试使用预先加载检索它们时,它不会加载列表。我在包含中列出了 LineSegment 的属性,但它不起作用。我想我需要修改模型中的关系设置,但我不确定如何修改。 如何更正此问题,以便在加载多边形时立即加载 LineSegments 列表?这是查询:
private static List<Expression<Func<Polygon, object>>> polygonRegionNaviationProperties = new List<Expression<Func<Polygon, object>>>()
{
(polygon => polygon.BasePoint),
(polygon => polygon.BasePoint.X),
(polygon => polygon.BasePoint.Y),
(polygon => polygon.BasePoint.Z),
(polygon => polygon.NormalVector),
(polygon => polygon.NormalVector.Direction),
(polygon => polygon.NormalVector.Direction.Phi),
(polygon => polygon.NormalVector.Direction.Theta),
(polygon => polygon.NormalVector.Magnitude),
(polygon => polygon.NormalVector.BasePoint.X),
(polygon => polygon.NormalVector.BasePoint.Y),
(polygon => polygon.NormalVector.BasePoint.Z),
(polygon => polygon.LineSegments),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.Direction)),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.Direction.Phi)),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.Direction.Theta)),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.Magnitude)),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.BasePoint.X)),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.BasePoint.Y)),
(polygon => polygon.LineSegments.Select(lineSegment => lineSegment.BasePoint.Z))
};
public Polygon GetPolygon(int? databaseId)
{
if(databaseId != null)
{
Polygon retrievedPolygon = Query((polygon => polygon.DatabaseId == databaseId), polygonRegionNaviationProperties);
return retrievedPolygon;
}
else
{
return null;
}
}
public override Polygon Query(Expression<Func<Polygon, bool>> match, List<Expression<Func<Polygon, object>>> includes = null)
{
using (var databaseContext = new ClearspanDatabaseContext())
{
databaseContext.Database.Log = Console.Write;
if (includes != null)
{
var dataSet = databaseContext.Set<Polygon>(); // Get the relevant DataSet
Polygon retrievedObject = includes.Aggregate( // Eagerly load the passed navigation properties
dataSet.AsQueryable(),
(current, include) => current.Include(include)
).SingleOrDefault(match);
databaseContext.Entry(retrievedObject).Collection(polygon => polygon.LineSegments).Load();
return retrievedObject;
}
else
{
Polygon retrievedObject = databaseContext.Set<Polygon>().SingleOrDefault(match);
databaseContext.Entry(retrievedObject).Collection(polygon => polygon.LineSegments).Load();
return retrievedObject;
}
}
}
更新
这是一个 link 到一个细化的 project 来说明我的问题。
- 克隆它。
- 初始化子模块(项目根目录中的
git submodule init
和git submodule update
)(如果您使用SourceTree,这可能会自动发生) - 运行 PostgreSQL 脚本,请注意您不能 运行 一次性完成所有操作,因为它正在创建数据库。关注顶部的评论。
- 运行 单元测试,请注意,除了 InsertAndRetrievePolygon 之外,它们都应该通过。那是因为没有检索到列表,您可以通过将鼠标悬停在调试器中的变量上来查看。
希望对理解、诊断和解决这个问题有所帮助。您会注意到,在我的问题中,我简化了 GeometryClassLibrary 中实际存在的层次结构。谢谢,斯科特 H
尝试按如下方式更改您的 class:
public class Polygon
{
public virtual List<LineSegment> LineSegments
{
get;
set;
}
// ...
}
在您的查询中,仅包含导航属性。不应包含字符串、原始类型和枚举类型。像这样:
var dataSet = databaseContext.Set<Polygon>();
Polygon retrievedObject = dataSet.Include(i => i.LineSegments).SingleOrDefault(match);
return retrievedObject;
这对你有用吗?
我将在此处查看有关 Code First 中一对多关系的第一个示例。 http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx
我认为 Fabio Luz 走在正确的轨道上。 LineSegments 集合应该是虚拟的。您还可以尝试覆盖默认构造函数并实例化 属性。另外,LineSegmentsclass中的Polygon大概应该有一个virtual属性来完成引用关系。
public class Polygon
{
public Polygon()
{
LineSegments = new List<LineSegment>();
}
public virtual List<LineSegment> LineSegments
{
get;
set;
}
// ...
}
public class LineSegment
{
public virtual Polygon Polygon { get; set; }
}
这是Polygon.LineSegments
的代码:
public virtual List<LineSegment> LineSegments
{
get { return this._Edges.Select(e => (LineSegment)e).ToList(); }
set { _Edges = value.ToList<IEdge>(); }
}
当 EF 填充子集合时,它不会为其分配 complete 集合,但会在必要时对其进行初始化,然后向其添加项目。现在陷阱来了:EF 将项目添加到哪个集合?不是 _Edges
,而是 ToList()
每次处理 LineSegments
时构建的临时集合。 _Edges
本身仍然是空的。
不幸的是,你不能通过 Include()
-ing Edges
代替 LineSegments
来解决这个问题,因为这是 Edges
的代码:
protected List<IEdge> _Edges = new List<IEdge>();
public virtual List<IEdge> Edges
{
get { return _Edges; }
set { _Edges = value; }
}
并且 EF 不支持接口。坦率地说,我不知道是否有合适的解决方法。 LineSegments
中的这种间接访问可能会导致更多 EF 问题。例如,我认为 关系修复 (从加载到上下文中的实体自动填充导航属性)也不会 运行。
我知道这些 类 来自外部图书馆。我看到所有这些 XyzEntityFramework
部分 类 那里(例如 LineSegmentEntityFramework
)似乎添加了属性以促进使用 EF。也许他们愿意查看您的问题并找到解决方案。