Мой код работает, но я получаю 2 дополнительных столбца в таблице / ddl, которые представляют отношение «многие ко многим», ~~ но ~~ с атрибутами (скалярами) в отношении.
Я использую
1.2.0.712 (FluentNHibernate.dll)
3.1.0.4000 (NHibernate.dll)
Объекты:
public partial class Employee
{
public Employee()
{
CommonConstructor();
}
private void CommonConstructor()
{
this.MyEmployeeToJobTitleMatchLinks = new List<EmployeeToJobTitleMatchLink>();
}
public virtual Guid? EmployeeUUID { get; set; }
public virtual byte[] TheVersionProperty { get; set; }
public virtual string SSN { get; set; }
public virtual string LastName { get; set; }
public virtual string FirstName { get; set; }
public virtual DateTime CreateDate { get; set; }
public virtual DateTime HireDate { get; set; }
public virtual ICollection<EmployeeToJobTitleMatchLink> MyEmployeeToJobTitleMatchLinks { get; set; }
public virtual void AddJobTitleLink(EmployeeToJobTitleMatchLink link)
{
link.TheEmployee = this;
if (!this.MyEmployeeToJobTitleMatchLinks.Contains(link))
{
this.MyEmployeeToJobTitleMatchLinks.Add(link);
}
if (!link.TheJobTitle.MyJobTitleToEmployeeMatchLinks.Contains(link))
{
link.TheJobTitle.MyJobTitleToEmployeeMatchLinks.Add(link);
}
}
public virtual void RemoveJobTitleLink(EmployeeToJobTitleMatchLink link)
{
link.TheEmployee = this;
if (this.MyEmployeeToJobTitleMatchLinks.Contains(link))
{
this.MyEmployeeToJobTitleMatchLinks.Remove(link);
}
if (link.TheJobTitle.MyJobTitleToEmployeeMatchLinks.Contains(link))
{
link.TheJobTitle.MyJobTitleToEmployeeMatchLinks.Remove(link);
}
}
}
public partial class JobTitle
{
public JobTitle()
{
CommonConstructor();
}
private void CommonConstructor()
{
this.MyJobTitleToEmployeeMatchLinks = new List<EmployeeToJobTitleMatchLink>();
}
public virtual Guid? JobTitleUUID { get; set; }
public virtual byte[] TheVersionProperty { get; set; }
public virtual string JobTitleName { get; set; }
public virtual DateTime CreateDate { get; set; }
public virtual ICollection<EmployeeToJobTitleMatchLink> MyJobTitleToEmployeeMatchLinks { get; set; }
public virtual void AddEmployeeLink(EmployeeToJobTitleMatchLink link)
{
link.TheJobTitle = this;
if (!this.MyJobTitleToEmployeeMatchLinks.Contains(link))
{
this.MyJobTitleToEmployeeMatchLinks.Add(link);
}
if (!link.TheEmployee.MyEmployeeToJobTitleMatchLinks.Contains(link))
{
link.TheEmployee.MyEmployeeToJobTitleMatchLinks.Add(link);
}
}
public virtual void RemoveEmployeeLink(EmployeeToJobTitleMatchLink link)
{
link.TheJobTitle = this;
if (this.MyJobTitleToEmployeeMatchLinks.Contains(link))
{
this.MyJobTitleToEmployeeMatchLinks.Remove(link);
}
if (link.TheEmployee.MyEmployeeToJobTitleMatchLinks.Contains(link))
{
link.TheEmployee.MyEmployeeToJobTitleMatchLinks.Remove(link);
}
}
}
public partial class EmployeeToJobTitleMatchLink
{
public EmployeeToJobTitleMatchLink()
{
//this.Id = Guid.NewGuid(); /* this works in conjuction with <generator class="assigned"></generator> */
}
public virtual Guid? LinkSurrogateUUID { get; set; }
/* These are "scalar properties of the ~~relationship~~ */
public virtual int PriorityRank { get; set; }
public virtual DateTime JobStartedOnDate { get; set; }
public virtual Employee TheEmployee { get; set; }
public virtual JobTitle TheJobTitle { get; set; }
}
Отображения:
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Id(x => x.EmployeeUUID).GeneratedBy.GuidComb();
OptimisticLock.Version();
Version(x => x.TheVersionProperty)
.Column("MyVersionColumn")
.Not.Nullable()
.CustomSqlType("timestamp")
.Generated.Always();
Map(x => x.SSN);
Map(x => x.LastName);
Map(x => x.FirstName);
Map(x => x.CreateDate);
Map(x => x.HireDate);
HasMany(x => x.MyEmployeeToJobTitleMatchLinks)
.Inverse()
.Cascade.All();
}
}
public class JobTitleMap : ClassMap<JobTitle>
{
public JobTitleMap()
{
Id(x => x.JobTitleUUID).GeneratedBy.GuidComb();
OptimisticLock.Version();
Version(x => x.TheVersionProperty)
.Column("MyVersionColumn")
.Not.Nullable()
.CustomSqlType("timestamp")
.Generated.Always();
Map(x => x.JobTitleName);
Map(x => x.CreateDate);
HasMany(x => x.MyJobTitleToEmployeeMatchLinks)
.Inverse()
.Cascade.All();
}
}
public class EmployeeToJobTitleMatchLinkMap : ClassMap<EmployeeToJobTitleMatchLink>
{
public EmployeeToJobTitleMatchLinkMap()
{
Id(x => x.LinkSurrogateUUID).GeneratedBy.GuidComb();
Map(x => x.PriorityRank);
Map(x => x.JobStartedOnDate);
References(x => x.TheEmployee).Column("TheEmployeeUUID").Not.Nullable();/*Bad naming convention with "The", but left here so it can be seen easily in the DDL*/
References(x => x.TheJobTitle).Column("TheJobTitleUUID").Not.Nullable();/*Bad naming convention with "The", but left here so it can be seen easily in the DDL*/
}
}
Это отлично работает, но я получаю 2 дополнительных (обнуляемых) столбца в ddl. Они помечены звездочкой (*) ниже.
Выберите * Из [dbo]. [EmployeeToJobTitleMatchLink]
LinkSurrogateUUID
PriorityRank
JobStartedOnDate
TheEmployeeUUID
TheJobTitleUUID
* EMPLOYEE_ID
* JobTitle_id
Я понимаю, что это "условно". (Имена с "_id" на них).
Но мне не нужны эти столбцы. И мне нужно иметь возможность настраивать имена.
(TheEmployeeUUID и TheJobTitleUUID в этом фиктивном примере.)
Моя финальная игра должна иметь:
Выберите * Из [dbo]. [EmployeeToJobTitleMatchLink]
LinkSurrogateUUID (UniqueIdentifier, SurrogateKey)
PriorityRank (скаляр, int)
JobStartedOnDate (скаляр, дата и время)
TheEmployeeUUID (UniqueIdentifier, FK возвращается к dbo.Employee.EmployeeUUID)
TheJobTitleUUID (UniqueIdentifier, FK возвращается к dbo.JobTitle.JobTitleUUID)
Атрибут (ы) в отношении ~ очень важно сохранить. (PriorityRank и JobStartedOnDate в этом примере макета.)
Спасибо.
Я так близко.
EDIT:
Отображения, которые работают:
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Id(x => x.EmployeeUUID).GeneratedBy.GuidComb();
OptimisticLock.Version();
Version(x => x.TheVersionProperty)
.Column("MyVersionColumn")
.Not.Nullable()
.CustomSqlType("timestamp")
.Generated.Always();
Map(x => x.SSN);
Map(x => x.LastName);
Map(x => x.FirstName);
Map(x => x.CreateDate);
Map(x => x.HireDate);
HasMany(x => x.MyEmployeeToJobTitleMatchLinks)
.Inverse()
.Cascade.All()
.KeyColumn("TheEmployeeUUID")
;
}
}
public class JobTitleMap : ClassMap<JobTitle>
{
public JobTitleMap()
{
Id(x => x.JobTitleUUID).GeneratedBy.GuidComb();
OptimisticLock.Version();
Version(x => x.TheVersionProperty)
.Column("MyVersionColumn")
.Not.Nullable()
.CustomSqlType("timestamp")
.Generated.Always();
Map(x => x.JobTitleName);
Map(x => x.CreateDate);
HasMany(x => x.MyJobTitleToEmployeeMatchLinks)
.Inverse()
.Cascade.All()
.KeyColumn("TheJobTitleUUID")
;
}
}
public class EmployeeToJobTitleMatchLinkMap : ClassMap<EmployeeToJobTitleMatchLink>
{
public EmployeeToJobTitleMatchLinkMap()
{
Id(x => x.LinkSurrogateUUID).GeneratedBy.GuidComb();
Map(x => x.PriorityRank);
Map(x => x.JobStartedOnDate);
References(x => x.TheEmployee).Column("TheEmployeeUUID").Not.Nullable();/*Bad naming convention with "The", but left here so it can be seen easily in the DDL*/
References(x => x.TheJobTitle).Column("TheJobTitleUUID").Not.Nullable();/*Bad naming convention with "The", but left here so it can be seen easily in the DDL*/
}
}
Спасибо, Натан!
PS
Один новый термин, который я выучил, пока гуглял / глотал, был
"объективированные отношения"
Это было в области комментариев этой страницы:
LINK1
В случае, если эта страница когда-нибудь умрет, вот что прокомментировано вставлено в:
Это называется «объективированным отношением» (ref: http://www.orm.net), а в NIAM / ORM это обычно определяется как отношение, которое само по себе является сущностью с атрибутами. Объективированное отношение всегда формирует по крайней мере отношения один к одному.
(С http://weblogs.asp.net/fbouma/)