I would like to create a OneToOne mapping between two of my entities, using non-primary columns. How do I configure this in NHibernate ?
Entities:
public class DocumentLock
{
public virtual long Id { get; set; }
public virtual string LockedBy { get; set; }
public virtual string DocumentCode { get; set; }
public virtual LegalDocument LegalDocument { get; set; }
}
public class LegalDocument
{
public virtual long Id { get; set; }
public virtual string Title { get; set; }
public virtual string DocumentCode { get; set; }
public virtual DocumentLock DocumentLock { get; set; }
}
Note: DocumentCode
is a string generated in the application, it's unique for each DocumentLock
and LegalDocument
Mappings:
public class DocumentLockMap : ClassMapping<DocumentLock>
{
public DocumentLockMap()
{
ManyToOne(x => x.LegalDocument, map =>
{
map.Column("DocumentCode");
map.Insert(false);
map.Update(false);
map.Unique(true);
map.Cascade(Cascade.None);
});
}
}
public class LegalDocumentMap : ClassMapping<LegalDocument>
{
public LegalDocumentMap()
{
OneToOne(x => x.DocumentLock, map =>
{
map.PropertyReference(x => x.LegalDocument);
map.Cascade(Cascade.All.Include(Cascade.DeleteOrphans));
map.Fetch(FetchKind.Join);
map.Constrained(true);
});
}
}
Query code:
using (var session = _sessionFactory.OpenSession())
using (var transaction = session.BeginTransaction())
{
var data = session.QueryOver<LegalDocument>().List();
};
Generated query:
SELECT
this_.Id as id1_1_1_,
this_.Title as title2_1_1_,
this_.DocumentCode as documentcode3_1_1_,
documentlo2_.Id as id1_0_0_,
documentlo2_.LockedBy as lockedby2_0_0_,
documentlo2_.DocumentCode as documentcode3_0_0_
FROM
LegalDocument this_
inner join
DocumentLock documentlo2_
on this_.Id = documentlo2_.DocumentCode
My expectation for the generated query is: it should join using this_.DocumentCode
, not this_.Id
on this_.DocumentCode = documentlo2_.DocumentCode
Thanks @Firo and @Roman Artiukhin.
Solution: use ManyToMany
on both mappings
So in my case, I'll use:
public class DocumentLockMap : ClassMapping<DocumentLock>
{
public DocumentLockMap()
{
ManyToOne(x => x.LegalDocument, map =>
{
map.PropertyRef("DocumentCode");
map.Column("DocumentCode");
map.Insert(false);
map.Update(false);
map.Unique(true);
map.Cascade(Cascade.None);
});
}
}
public class LegalDocumentMap : ClassMapping<LegalDocument>
{
public LegalDocumentMap()
{
ManyToOne(x => x.DocumentLock, map =>
{
map.PropertyRef("DocumentCode");
map.Column("DocumentCode");
map.Insert(false);
map.Update(false);
map.Unique(true);
map.Cascade(Cascade.All.Include(Cascade.DeleteOrphans));
map.Fetch(FetchKind.Join);
});
}
}
Generated query:
SELECT
this_.Id as id1_1_1_,
this_.Title as title2_1_1_,
this_.DocumentCode as documentcode3_1_1_,
documentlo2_.Id as id1_0_0_,
documentlo2_.LockedBy as lockedby2_0_0_,
documentlo2_.DocumentCode as documentcode3_0_0_
FROM
LegalDocument this_
left outer join
DocumentLock documentlo2_
on this_.DocumentCode = documentlo2_.DocumentCode