Search code examples
nhibernatefluent-nhibernate

NHibernate Navigation Property for joining only


Take the following two entities: -

public class Product
{
    public virtual int Id { get; set; }

    public virtual string ItemId { get; set; }
}

public class ProductDescription
{
    public virtual int Id { get; set; }

    public virtual string ItemId { get; set; }

    public virtual string Description { get; set; }
}

These two entities are related by ItemId but there isn't always a ProductDescription for every ItemId that is stored against a Product.

What I want to do is set up a ProductDescription navigation property in the Product entity which I can then use in HQL in order perform joins etc. in the same way as I would any other navigation property. I don't want there to be a foreign key or any kind of enforced relationship.

My attempt at doing was as follows: -

public class Product
{
    public virtual int Id { get; set; }

    public virtual string ItemId => ProductDescription?.ItemId;

    public virtual ProductDescription ProductDescription { get; set; }
}

public class ProductMap
{
    public ProductMap()
    {
        Id(x => x.Id);
        References(x => x.ProductDescription).Not.Nullable().Column("ItemId").PropertyRef(x => x.ItemId).ForeignKey("none");
    }
}

This worked absolutely fine when reading existing data from the database with the navigation property working as I would expect when it comes to joins etc.

My unresolved issue is around the persistence of products. When I store a product, I don't want it to check anything to do with it's relationship with ProductDescriptions, I just want it to store the ItemId and if and when a ProductDescription with the matching ItemId is persisted, any joins that I perform using the Navigation property should work.

My attempt at persistence was as follows: -

new Product
{
    ProductDescription = new ProductDescription { ItemId = "SomeId" }
}

And this seems to work absolutely fine, until I try and make the ItemId on product non nullable at which point I get the usual error you get when you haven't set Inverse() on the other side the relation. However, even when I did create a HasMany relationship on ProductDescription with Inverse set, it still didn't solve the issue.

I hope that the above outlines what I am trying to do. I can get it to work almost exactly how I want except that I am forced to make the ItemId on Product nullable.

Any ideas how to solve this?


Solution

  • Seemed to have solved it.

    public class Product
    {
        public virtual int Id { get; set; }
    
        public virtual string ItemId { get; set; }
    
        public virtual ProductDescription ProductDescription { get; protected set; }
    }
    
    public class ProductMap
    {
        public ProductMap()
        {
            Id(x => x.Id);
            Map(x => x.ItemId).Not.Nullable();
            References(x => x.ProductDescription).Column("ItemId").PropertyRef(x => x.ItemId).ForeignKey("none").ReadOnly();
        }
    }
    

    This allows me to set the item id on either side of the relationship freely and without constraint. The navigation property works as expected too.