我有一个表PolygonMapping
,其寄存器包含polygon id
和其他相关表的其他ID。
Polygon
表仅包含其ID
。
还有line
表,其寄存器包含polygon_ID
的一部分,以及几个points_Id
(start point
和end point
)。
point
表仅包含2 coordinates
(X
和Y
)。
我对如何使用NHibernate for C#映射此数据库结构感到困惑。我希望能够轻松访问lines
的{{1}}(所以我认为polygon
类中的行列表会很好),我希望能够要在我想更新一个点polygon
或PolygonMapping
时仅保存line
课程。我想自动完成它。
请帮助我!
谢谢。
答案 0 :(得分:1)
我会通过创建三个域模型对象来映射此问题:描述点的Point对象,包含两个Point对象的Line对象,一个名为“StartPoint”和一个名为“EndPoint”的对象,以及一个Polygon对象包含一个IEnumerable of Lines。域对象看起来像这样:
public class Point
{
public int Id { get; set; }
public int XVal {get; set;}
public int YVal {get; set;}
}
public class Line
{
public int Id {get; set;}
public Point StartPoint {get; set;}
public Point EndPoint {get; set;}
}
public class Polygon
{
public Polygon()
{
Lines = new HashSet<Line>();
}
public int Id {get; set;}
public string Description { get; set; }
public ICollection<Line> Lines { get; set; }
}
您可以使用具有每个域模型对象的表的数据库模式来持久化此类。
创建此数据库结构的SQL DDL如下:
create table Point
(
PointId int primary key identity(1, 1),
XVal int,
YVal int
)
create table Polygon
(
PolygonId int primary key identity(1, 1),
[Description] nvarchar(255)
)
create table Line
(
LineId int primary key identity(1, 1),
PolygonId int foreign key references Polygon(PolygonId),
StartPointId int foreign key references Point(PointId),
EndPointId int foreign key references Point(PointId)
)
您的最后一项任务是编写nHibernate映射文件,以将域模型映射到基础数据库表。这可以如下所示完成。请注意,我将“cascade”属性设置为“all”,以满足保存父Polygon对象将更改级联到子对象的要求。
<class name="Polygon" table="Polygon" lazy="false" >
<id name="Id" column="PolygonId">
<generator class="identity" />
</id>
<property name="Description" column="Description" />
<set name="Lines" table="Line" lazy="false" cascade="all">
<key column="PolygonId" />
<one-to-many class="Line" />
</set>
</class>
<class name="Line" table="Line" lazy="false">
<id name="Id" column="LineId">
<generator class="identity" />
</id>
<many-to-one name="StartPoint" column="StartPointId" class="Point" cascade="all"/>
<many-to-one name="EndPoint" column="EndPointId" class="Point" cascade="all"/>
</class>
</hibernate-mapping>
使用此映射,您可以操作父Polygon对象,并在保存时将整个对象图持久保存到数据库。例如,要向Polygon对象添加新行,可以使用以下代码段:
using (var session = factory.OpenSession())
using(var tran = session.BeginTransaction())
{
var newPoint = session.Get<Point>(5);
var newPoint2 = session.Get<Point>(2);
var newLine = new Line { StartPoint = newPoint, EndPoint = newPoint2 };
var foo2 = session.Get<Polygon>(1);
foo2.Lines.Add(newLine);
session.SaveOrUpdate(foo2);
tran.Commit();
}
修改强> 上面的映射假定您始终只想通过父Polygon对象访问Line对象。如果要直接访问Lines,可能需要将Line对象中的多对一引用添加到Polygon父级。为此,您需要将以下属性添加到Line类:
public Polygon Polygon {get; set;}
以及在行映射文件中添加相应的映射:
<many-to-one class="Polygon" name="Polygon" lazy="false" />
通过这些更改,您现在应该能够直接加载包含它的Polygon父级的Line对象:
var line = session.Get<Line>(5);
var parent = line.Polygon;
编辑2 请注意,如果将多边形线关联设置为双向,则需要向域模型添加代码以确保图形一致性。请参阅示例this SO post。