TimeSheetActivity类有一组Allocations。分配是一个值对象(不可变),看起来像这样:
public class Allocation : ValueObject {
public virtual StaffMember StaffMember { get; private set; }
public virtual TimeSheetActivity Activity { get; private set; }
public virtual DateTime EventDate { get ... }
public virtual TimeQuantity TimeSpent { get ... }
}
在域中使用此关系的最方便方法是使用IDictionary,即:
public virtual IEnumerable<Allocation> Allocations {
get { return _allocations.Values; } }
private readonly IDictionary<DateTime, Allocation> _allocations = new SortedList<DateTime, Allocation>();
我还需要能够持续并通过StaffMember获取分配。如果这是一个数据驱动的设计,我的概念是会有一个Allocations表来解决Activities和StaffMembers之间的多对多关系:
table Allocations
ActivityID
StaffMemberID
EventDate
TimeQuantity
我无法直观地显示映射。我试图从TimeSheetActivity的Allocations开始,但是当我尝试生成DDL时,我得到以下错误:
NHibernate.MappingException:(XmlDocument)(3,6):XML验证错误:命名空间'urn:nhibernate-mapping-2.2'中的元素'class'在命名空间'urn:nhibernate-中具有无效的子元素'property'映射-2.2' 。期望的可能元素列表:命名空间'urn:nhibernate-mapping-2.2'中的'meta,subselect,cache,synchronize,comment,tuplizer,id,composite-id'。
我无法判断我是否收到错误,因为:
A). I haven't yet mapped StaffMember to a collection of Allocations.
B). The mapping I have between Activity and Allocations is wrong.
C). All of the above
D). Other _____________________________________
AllocationMapping(在FNH中)
public class AllocationMap : IAutoMappingOverride<Allocation>
{
public void Override(AutoMap<Allocation> mapping)
{
// these are both derived from the time period, so ignore
mapping.IgnoreProperty(x => x.TimeSpent);
mapping.IgnoreProperty(x => x.EventDate);
// TimePeriodUserType knows how to persist the time period start and end dates as DateTimes
mapping.Map(x => x.TimeSpentPeriod)
.ColumnNames.Add("PeriodStart", "PeriodEnd")
.SetAttribute("type", typeof(TimePeriodUserType).AssemblyQualifiedName);
mapping.References(x => x.Activity).WithForeignKey().FetchType.Join().Not.Nullable();
mapping.References(x => x.StaffMember).WithForeignKey().FetchType.Join().Not.Nullable();
}
}
分配映射(生成的hbm)
....
<property name="TimeSpentPeriod" type="..., ..., ...">
<column name="PeriodStart" />
<column name="PeriodEnd" />
</property>
<many-to-one foreign-key="FK_AllocationToStaffMember" fetch="join" not-null="true" name="StaffMember" column="StaffMemberID" />
<many-to-one foreign-key="FK_AllocationToActivity" fetch="join" not-null="true" name="Activity" column="TimeSheetActivityID" />
....
活动图(FNH)
public class TimeSheetActivityMap : IAutoMappingOverride<TimeSheetActivity>
{
public void Override(AutoMap<TimeSheetActivity> mapping)
{
// this can be replaced by some id given by NHib via an inheritance type mapping??
mapping.IgnoreProperty(x => x.IdScheme);
// this is derived
mapping.IgnoreProperty(x => x.TotalTime);
// this is for client consumption only
mapping.IgnoreProperty(x => x.Allocations);
mapping.HasMany(x => x.Allocations)
.AsMap(x => x.EventDate)
.Cascade.All()
.Access.AsCamelCaseField(Prefix.Underscore)
.WithForeignKeyConstraintName("FK_ActivityAllocation");
}
}
ActivityMapping(生成的hbm)
<set name="Allocations" cascade="all" access="field.camelcase-underscore">
<key foreign-key="FK_ActivityAllocation" column="TimeSheetActivityID" />
<one-to-many class="Smack.ConstructionAdmin.Domain.Model.TimeSheet.Allocation, ..." />
</set>
这是我对NHibernate的经验水平的复杂映射,所以我很欣赏任何有关映射技术,建模概念或我的解决方法的帮助,问题或批评。
干杯, Berryl
答案 0 :(得分:2)
我不是FHN的专家,但我发现您的Allocations属性是作为Set生成的。你应该得到一个像这样的Map元素:
<map name="Allocations" lazy="true" table="Allocations">
<key column="FK_ActivityAllocation"/>
<index column="EVENT_DATE" type="DateTime"/>
<composite-element class="Allocation">
...
</composite>
</map>
这里有一些高级示例: http://ayende.com/Blog/archive/2009/06/03/nhibernate-mapping-ndash-ltmapgt.aspx