我在尝试使用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)
)
产品表的生成存在一些错误:
发生了什么事?
答案 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");
}
}