如何映射此模型

时间:2009-07-05 08:28:42

标签: c# nhibernate fluent-nhibernate nhibernate-mapping domain-driven-design

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

1 个答案:

答案 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