流畅的NHibernate映射计算具有多对多和额外字段

时间:2011-11-09 14:18:05

标签: nhibernate map components fluent

我一直在同一个地方旋转,试图通过额外列的多对多表来解决这个问题。如果你能在这里帮忙的话,我正在吞下我的骄傲,并请更多经验丰富的Fluent NHibernate专家。

我一直在尝试将组件用于多对多表,但我似乎没有找到指向该组件的位置以在特定列上进行连接。我想只要我填充完成信息对象,就不需要组件的存在和使用。

这是我的简化架构。

User
...................
Id
Name 

Task
...................
Id
Name


Job
...................
Id
Name

JobTask
...................
JobId
TaskId
CompletedByUserId
CompletionDate
CompletionNotes

然后我有这样的对象:

 public class Job
 {
    long Id { get; set; }
    IList<Task> Tasks { get; set; }
 }


 public class Task
 {
    long Id { get; set; }
    string Name { get; set; }
    CompletionInfo CompletionInfo { get; set; }
 }

 public class CompletionInfo
 {
    User User { get; set; }
    DateTime CompletionDate { get; set; }
 }

你能帮助你的想法如何用流利的nhibernate实现这个吗?

我之前在JobMap上有这个映射,它可以工作,但只适用于多对多列(TaskId,JobId)。我需要与该关系相关的额外信息(dateCompleted,userCompleted等)

 HasManyToMany<Task>(job => job.Tasks)
            .Table(ManyToManyTable)
             .ParentKeyColumn("JobId")
            .ChildKeyColumn("TaskId")
            .Not.LazyLoad()
            .Cascade.Delete();

为了简化多对多的事情,我想创建一个对象来表示关系并封装任务。像这样: 我会在Job任务中添加一个代理来修改实际的Task属性。但这不会发生在任何地方。

这一定是常见的事情,我对这个问题并不多感到惊讶。 当然我会喜欢扩展HasManyToMany的方法,但不知道如何,因此这篇文章。

public class JobTask : Entity<long, JobTask>
{ 
    public virtual Job ParentJob { get; set; }

    public virtual Task Task   { set;set; }

    public virtual TaskCompletionDetails CompletionInformation
    {
        get
        {
            if (this.Task == null)
                return null;

            return Task.CompletionInformation;
        }

        set
        {
            if (this.Task == null)
                return;

            this.Task.CompletionInformation = value;
        }
    }


    public virtual string CompletionNotes
    {
        get
        {
            if (this.Task == null || this.Task.CompletionInformation == null)
                return null;

            return Task.CompletionInformation.Notes;
        }

        set
        {
            if (this.Task == null)
                return;

            this.Task.CompletionInformation.Notes = value;
        }
    }

    public virtual DateTime? CompletionDate
    {
        get
        {
            if (this.Task == null || this.Task.CompletionInformation == null)
                return null;

            return Task.CompletionInformation.Date;
        }

        set
        {
            if (this.Task == null)
                return;

            this.Task.CompletionInformation.Date = value;
        }
    }

    public virtual IUser User
    {
        get
        {
            if (this.Task == null || this.Task.CompletionInformation == null)
                return null;

            return Task.CompletionInformation.User;
        }

        set
        {
            if (this.Task == null || value == null)
                return;

            if (this.Task.CompletionInformation != null)
                this.Task.CompletionInformation.User = value;
        }
       }
    }
 }

这是我为它开始的地图方向:

public class JobTaskMap : ClassMap<JobTask>
{
    private const string ModelTable = "[JobTasks]";

    public JobTaskMap()
    {
        Table(ModelTable);

        Id(jobTask => jobTask.Id)
            .Column("Id")
            .GeneratedBy.Identity();

        References<Job>( jobTask => jobTask.ParentJob)
            .Column("JobId")
            .Fetch.Join();

        Component<Task>( jobTask => (Task) jobTask.Task,
                // This is the task
                 comp =>
                 { 
                     // This is the task completion information
                     comp.Component<TaskCompletionDetails>(
                         task => (TaskCompletionDetails)task.CompletionInformation,
                         compInfo =>
                         {    
                             compInfo.Map(info => info.Date)
                                .Column("CompletionDate")
                                .Nullable();

                             compInfo.Map(info => info.Notes)
                                .Column("CompletionNotes")
                                .Nullable();

                             compInfo.References<User>(info => info.User)
                                .Column("CompletedByUserId")
                                .Nullable()
                                .Fetch.Join();
                         });  
                 });

    }

这些是其他一些我没有成功的相关阅读:

参考:

http://wiki.fluentnhibernate.org/Fluent_mapping

Fluent Nhibernate Many-to-Many mapping with extra column

1 个答案:

答案 0 :(得分:0)

这是一种取决于所使用的id生成策略的方式。如果使用Identity则不会这样做(至少NH会因各种原因阻止使用Identity),但是每个插入id本身的策略都会起作用:

class JobMap : ClassMap<Job>
{
    public JobMap()
    {
        Id(x => x.Id);

        HasMany(x => x.Tasks)
            .KeyColumn("JobId");
    }
}

class TaskMap : ClassMap<Task>
{
    public TaskMap()
    {
        Table("JobTask");
        Id(x => x.Id, "TaskId");

        Component(x => x.CompletionInfo, c =>
        {
            c.Map(x => x.CompletionDate);
            c.References(x => x.User, "CompletedByUserId");
        });

        Join("Task", join =>
        {
            join.Map(x => x.Name, "Name");
        });
    }
}