views:

426

answers:

1

I am having a number of problems trying to map entities using Fluent NHibernate.

I have three entities, like this:

public class Product
{
    public virtual Guid Id { get; set; }
    public virtual Category Category { get; set; }
    public virtual Seller Seller { get; set; }
}

public class Seller
{
    public virtual Guid Id { get; set; }
    public virtual IList<Product> Products { get; set; }
}

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

Notice that the Category uses an int for its ID, whereas the other classes use Guids.

My mapping classes look like this:

public sealed class ProductDbMap : ClassMap<Product>
{
    public ProductDbMap()
    {
        Id(x => x.Id);

        References(x => x.Seller)
            .Not.Nullable();

        References(x => x.Category, "Category")
            .Nullable();
    }
}

public sealed class SellerDbMap : ClassMap<Seller>
{
    public SellerDbMap()
    {
        Id(x => x.Id);

        HasMany(x => x.Products);
    }
}

public sealed class CategoryDbMap : ClassMap<Category>
{
    public CategoryDbMap()
    {
        Id(x => x.Id);
    }
}

Finally, I have the following convention, which specifies how reference id columns should be named:

public class ReferenceConventions : IReferenceConvention
{
    public bool Accept(IManyToOnePart target)
    {
        return true;
    }

    public void Apply(IManyToOnePart target)
    {
        target.ColumnName(target.Property.Name + "Id");
    }
}

Here is how NHibernate decides to generate the tables:

create table Product (
   Id UNIQUEIDENTIFIER not null,
   SellerId UNIQUEIDENTIFIER not null,
   CategoryId INTEGER,
   Seller_id UNIQUEIDENTIFIER,
   primary key (Id)
)

create table Seller (
   Id UNIQUEIDENTIFIER not null,
   primary key (Id)
)

create table Category (
   Id  integer,
   primary key (Id)
)

There are a couple of errors with the generation of the Product table:

  1. The "SellerId" column is duplicated for some reason; the duplicate column does not follow my naming convention.
  2. I am trying to override my naming convention for the "CategoryId" column, by supplying a value of "Category" to the References method. However, the table still uses the convention instead.

What is going on?

A: 

Answering my own question here.

1) The duplicate columns occur because I need to add a HasManyConvention in addition to the ReferenceConvention. The two working together will cause only column to be created. The code for the HasManyConvention is:

public class HasManyConventions : IHasManyConvention
{
    public bool Accept(IOneToManyPart target)
    {
        return true;
    }

    public void Apply(IOneToManyPart target)
    {
        target.KeyColumnNames.Add(target.EntityType.Name + "Id");
    }
}

2) The second problem seems to be something weird with Fluent NHibernate's conventions. It was my understanding that the ClassMap's column name should override the convention (this makes logical sense and is a lot more useful). However this doesn't seem to be occurring. The problem can be solved by checking if the column name is null in the convention:

public class ReferenceConventions : IReferenceConvention
{
    public bool Accept(IManyToOnePart target)
    {
        return true;
    }

    public void Apply(IManyToOnePart target)
    {
        if (target.GetColumnName() == null)
            target.ColumnName(target.Property.Name + "Id");
    }
}
cbp

related questions