我一直在同一个地方旋转,试图通过额外列的多对多表来解决这个问题。如果你能在这里帮忙的话,我正在吞下我的骄傲,并请更多经验丰富的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();
});
});
}
这些是其他一些我没有成功的相关阅读:
参考:
答案 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");
});
}
}