2010-03-25 21 views
1

如果这是一个天真的问题,首次使用NHibernate/Fluent摇摆它,所以提前道歉。我有一套我想要映射的模型。当我创建会话工厂时,我试图一次完成所有映射。我没有使用自动映射(尽管如果我正在尝试做的事情最终会变得比它应该更痛苦)。我遇到的问题是,似乎只有顶级地图正在采取。给定下面的代码片段并运行一个试图保存'bar'的单元测试,它会失败并检查我看到的日志NHibernate试图将一个bar实体保存到foo表中。虽然我怀疑这是我的映射,但它可能是我简单忽略的其他东西。创建会话工厂如何使用FluentHibernate配置多个映射?

代码(注意我也试过单独调用到.Mappings):

Fluently.Configure().Database(MsSqlConfiguration.MsSql2008 
    .ConnectionString(c => c 
     .Server(@"localhost\SQLEXPRESS") 
     .Database("foo") 
     .Username("foo") 
     .Password("foo"))) 
    .Mappings(m => 
     { 
      m.FluentMappings.AddFromAssemblyOf<FooMap>() 
       .Conventions.Add(FluentNHibernate.Conventions.Helpers 
       .Table.Is(x => "foos")); 
      m.FluentMappings.AddFromAssemblyOf<BarMap>() 
       .Conventions.Add(FluentNHibernate.Conventions.Helpers 
       .Table.Is(x => "bars")); 
     }) 
    .BuildSessionFactory(); 

单元测试代码片段:

using (var session = Data.SessionHelper.SessionFactory.OpenSession()) {  
    var bar = new Bar(); 
    session.Save(bar); 
    Assert.NotNull(bar.Id); 
} 

回答

2

你做错了。 :)

首先,m.FluentMappings.AddFromAssemblyOf<FooMap>()m.FluentMappings.AddFromAssemblyOf<BarMap>()都在做同样的事情(如果FooMapBarMap在同一个组件)。每一个只是告诉Fluent NHibernate扫描包含泛型类型的程序集;所以如果两个类型都在同一个程序集中,它会扫描两次。

其次,Conventions调用没有作用于您所调用的特定程序集,而是针对整个映射集。所以你要做的是提供两个约定来将表名设置为明确的值,而第二个约定是最后一个应用。你想要做的是使用x参数(这是实体类型)并从中创建表名。

你需要的是这样的:

.Mappings(m => 
{ 
    m.FluentMappings.AddFromAssemblyOf<FooMap>() 
    .Conventions.Add(Table.Is(x => x.Name + "s")); 
}) 

显然,我的实现是天真的,并根据你的表命名约定,你可能想使用一个pluraliser(我相信城堡有一个,但它不应该很难找到一个与谷歌)。

您可以通过Fluent NHibernate wiki了解关于conventions的更多信息。

+0

我想尽可能多,谢谢,这有助于。 – 2010-03-25 18:07:05

0

与您指定表名类映射mapping。如果未指定,则它将与实体类名称相同。

class FooMap : ClassMap<Foo> 
{ 
    public FooMap() 
    { 
     Table("foos"); 
    } 
} 

Conventions适用于所有映射。当您添加2个表名称约定时,只有1个会生效。

您的FooMap和BarMap是否在同一个程序集中?你只需要添加一个程序集。

.Mappings(m => m.FluentMappings.AddFromAssemblyOf<FooMap>()) 
+0

这也有帮助!在两个答案之间,我认为我很好去。 – 2010-03-25 18:07:59

0

只是想分享这个会自动添加复数名称或者s,es,ies基于结束字母表。不太确定语法和一些例外,但这对我来说似乎很好。任何异常使用Table("foos")就像@Lachlan罗氏所说。例如。 客户类将有客户表和类别类将有类别表。

修改@詹姆斯格雷戈里答案:

.Mappings(m => 
{ 
    m.FluentMappings.AddFromAssemblyOf<FooMap>() 
    .Conventions.Add(Table.Is(x => GetPluralName(x.Name)); 
}) 


public static string GetPluralName(string oldName) 
{ 
    // This is the very simple. Just ignore exception like days, boys, photos and other specific nouns. 
    if (oldName.EndsWith("y")) 
     return oldName.Remove(oldName.Length - 1) + "ies"; 
    else if (oldName.EndsWith("s") || oldName.EndsWith("e") || oldName.EndsWith("h") || oldName.EndsWith("z") || oldName.EndsWith("o")) // Sibilant consonant or "o" 
     return oldName + "es"; 
    return oldName + "s"; 
}