C# (流利)nHibernate:“;与引用一样,外键默认为Author_id,您可以覆盖它

C# (流利)nHibernate:“;与引用一样,外键默认为Author_id,您可以覆盖它,c#,nhibernate,fluent-nhibernate,C#,Nhibernate,Fluent Nhibernate,…使用KeyColumn方法,或使用约定更改默认行为。" 这段引语来自fluent nhibernate mapping guide。我不明白为什么它会这样做,而不是使用正确的(列)名称作为Author类主键 我知道一个解决方案,就是在我自己的映射中使用.KeyColumn(我的问题在代码后面): 公共类供应商映射:类映射 { 公共供应商地图() { 表(“供应商”); 懒散的负荷(); Id(x=>x.SupplierID,“SupplierID”); Map(x=>x.CompanyName

…使用KeyColumn方法,或使用约定更改默认行为。"

这段引语来自fluent nhibernate mapping guide。我不明白为什么它会这样做,而不是使用正确的(列)名称作为Author类主键

我知道一个解决方案,就是在我自己的映射中使用.KeyColumn(我的问题在代码后面):

公共类供应商映射:类映射
{
公共供应商地图()
{
表(“供应商”);
懒散的负荷();
Id(x=>x.SupplierID,“SupplierID”);
Map(x=>x.CompanyName).Not.Nullable();
Map(x=>x.ContactName);
地图(x=>x.ContactTitle);
映射(x=>x.Address);
地图(x=>x.City);
Map(x=>x.Region);
Map(x=>x.PostalCode);
地图(x=>x.Country);
地图(x=>x.Phone);
地图(x=>x.Fax);
地图(x=>x.HomePage);
HasMany(x=>x.Products).KeyColumn(“ProductID”).Inverse().Cascade.All();
}
}
产品映射为:

    public class ProductMap : ClassMap<Product> 
{

    public ProductMap() 
    {
    Table("Products");
    LazyLoad();
        Id(x => x.ProductID);
        References(x => x.Supplier, "SupplierID");
    Map(x => x.ProductName).Not.Nullable();
    Map(x => x.QuantityPerUnit);
        Map(x => x.UnitPrice);
    Map(x => x.UnitsInStock);
        Map(x => x.UnitsOnOrder);
        Map(x => x.ReorderLevel);
    Map(x => x.Discontinued).Not.Nullable();

    }
}
公共类ProductMap:ClassMap
{
公共产品地图()
{
表(“产品”);
懒散的负荷();
Id(x=>x.ProductID);
参考文件(x=>x.供应商,“供应商ID”);
映射(x=>x.ProductName).Not.Nullable();
Map(x=>x.QuantityPerUnit);
地图(x=>x.单价);
Map(x=>x.UnitsInStock);
Map(x=>x.UnitsOnOrder);
Map(x=>x.reordlevel);
Map(x=>x.contracted).Not.Nullable();
}
}

所以我的问题是,有没有更优雅的方法?我很失望地看到我的产品表上有两列id(ProductID和product_id)。如上所述,这是用KeyColumn(“ProductID”)修复的。有没有一种方法可以在产品映射中,甚至在配置中设置它?我想我不理解“用约定覆盖默认行为”--这可能就是答案所在。

您需要将
Product.Id
的列名指定为
ProductID


您所做的大部分工作都可以使用AutoMapper来完成。您需要将
Product.Id
的列名指定为
ProductID


您正在做的大部分工作可以首先使用AutoMapper来完成,如果您的FK都是这种格式的
ObjectNameID
,那么您可能需要执行自定义FK约定:

public class CustomForeignKeyConvention : ForeignKeyConvention
{
    protected override string GetKeyName(Member property, Type type)
    {
        if (property == null)
            return type.Name + "Id";

        return property.Name + "Id";
    }
}
这样就不必手动指定FK名称。如果不使用
Id
作为PK的属性名称,也可以执行PK约定

public class PrimaryKeyConvention : IIdConvention
{
    public void Apply(IIdentityInstance instance)
    {
        instance.Column(instance.EntityType.Name + "Id");
    }
}
(摘自)


我怀疑您使用的PK约定与FNH的期望不符,这是您在本例中的问题。

首先,如果您的FK都采用该格式
ObjectNameID
,则您可能需要执行自定义FK约定:

public class CustomForeignKeyConvention : ForeignKeyConvention
{
    protected override string GetKeyName(Member property, Type type)
    {
        if (property == null)
            return type.Name + "Id";

        return property.Name + "Id";
    }
}
这样就不必手动指定FK名称。如果不使用
Id
作为PK的属性名称,也可以执行PK约定

public class PrimaryKeyConvention : IIdConvention
{
    public void Apply(IIdentityInstance instance)
    {
        instance.Column(instance.EntityType.Name + "Id");
    }
}
(摘自)


我怀疑你使用的PK约定与FNH的期望不符,这是你在本案中的问题。

对于一个问题来说,这是一个糟糕的标题——想象一下,将来有人试图找到这个问题。我认为stackoverflow自己的搜索不是很好,我认为人们使用谷歌来找到答案——这是他们在stack上的初衷溢出…我怀疑这个标题在谷歌会有多大的不同。对于一个问题来说,这是一个糟糕的标题——想象一下将来有人试图找到这个问题。我不认为stackoverflow自己的搜索很好,我认为人们使用谷歌来找到答案——这就是他们在stackoverflow时想要的答案……我怀疑这个标题会让人失望在google中有很大的不同。我这样做了:Id(x=>x.ProductID,“ProductID”).Column(“ProductID”);我仍然可以在产品表中得到两个Id列……我这样做了:Id(x=>x.ProductID,“ProductID”).Column(“ProductID”);我仍然可以在product表中获得两个ID列……如果还没有尝试过,它看起来是一个很好的解决方案。如果还没有尝试过,它看起来是一个很好的解决方案。