=== CLARIFICATION ====
The 'answers' older than March are not answers to the question in this post!
Hello
In my domain I need to track allocations of time spent on Activities by resources. There are two general types of Activities of interest - ones base on a Project and ones based on an Account.
The notion of Project and Account have other features totally unrelated to both each other and capturing allocations of time, and each is modeled as a table in the database.
For a given Allocation of time however, it makes sense to not care whether the allocation was made to either a Project or an Account, so an ActivityBase class abstracts away the difference. An ActivityBase is either a ProjectActivity or an AccountingActivity (object model is below).
Back to the database though, there is no little direct value in having tables for ProjectActivity and AccountingActivity, as there is no requirement at this time to report Allocations by either Project or Account. There is one presentation where data is collected and it is useful to present both ProjectActivities and AccountActivities together, and be able to edit a row - to edit the activity some row id is needed, and a unique db Id is useful. The alternative to a db generated Id is one that concatenates the Activity.BusinessId (which for a Project is the Project.Code and for an Account is the Account.Number) along with the Type.
BUT the Allocation table needs to store something in the column for it's ActivityBase. Should that something be the Id of the Project / Account or a reference to tables for ProjectActivity / Accounting? How would the mapping look?
=== Current Db Mapping (Fluent) ====
Below is how the mapping currently looks (this has changed since the first post):
public class ActivityBaseMap : IAutoMappingOverride<ActivityBase>
{
public void Override(AutoMapping<ActivityBase> mapping)
{
mapping.IgnoreProperty(x => x.BusinessId);
mapping.IgnoreProperty(x => x.Description);
mapping.IgnoreProperty(x => x.TotalTime);
mapping.IgnoreProperty(x => x.UniqueId);
mapping.DiscriminateSubClassesOnColumn("SubClassType");
}
}
public class AccountingActivityMap : SubclassMap<AccountingActivity>
{
public AccountingActivityMap() {
References(x => x.Account);
DiscriminatorValue("ACCOUNT");
}
}
public class ProjectActivityMap : SubclassMap<ProjectActivity>
{
public ProjectActivityMap() {
References(x => x.Project);
DiscriminatorValue("PROJECT");
}
}
There are two odd smells here. Firstly, the inheritance chain adds nothing in the way of properties - it simply adapts Projects and Accounts into a common interface so that either can be used in an Allocation. Secondly, the properties in the ActivityBase interface are redundant to keep in the db, since that information is available in Projects and Accounts.
Cheers,
Berryl
==== Domain =====
public class Allocation : Entity
{
...
public virtual ActivityBase Activity { get; private set; }
...
}
public abstract class ActivityBase : Entity
{
public virtual string BusinessId { get; protected set; }
public virtual string Description { get; protected set; }
public virtual ICollection<Allocation> Allocations { get { return _allocations.Values; } }
public virtual TimeQuantity TotalTime {
get { return TimeQuantity.Hours(Allocations.Sum(x => x.TimeSpent.Amount)); }
}
}
public class ProjectActivity : ActivityBase
{
public virtual Project Project { get; private set; }
public ProjectActivity(Project project) {
BusinessId = project.Code.ToString();
Description = project.Description;
Project = project;
}
}