流畅的NHibernate:奇怪的列映射行为

时间:2009-09-08 07:44:27

标签: nhibernate mapping fluent

我在尝试使用Fluent NHibernate映射实体时遇到了一些问题。

我有三个实体,如:

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; }
}

请注意,Category使用int作为其ID,而其他类使用Guids。

我的映射类看起来像这样:

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);
    }
}

最后,我有以下约定,它指定了如何命名引用id列:

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

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

以下是NHibernate决定生成表的方法:

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)
)

产品表的生成存在一些错误:

  1. 由于某种原因,“SellerId”列被复制;重复列不遵循我的命名约定。
  2. 我试图通过向References方法提供“Category”值来覆盖“CategoryId”列的命名约定。但是,该表仍然使用约定。
  3. 发生了什么事?

1 个答案:

答案 0 :(得分:2)

在这里回答我自己的问题。

1)出现重复列,因为除了ReferenceConvention之外我还需要添加一个HasManyConvention。这两个一起工作将导致只创建列。 HasManyConvention的代码是:

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

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

2)第二个问题似乎与Fluent NHibernate的惯例有些奇怪。我的理解是ClassMap的列名应该覆盖约定(这具有逻辑意义,并且更有用)。然而,这似乎并没有发生。可以通过检查约定中的列名是否为空来解决该问题:

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");
    }
}