第一次用NHibernate / Fluent摇滚它,如果这是一个天真的问题,请提前道歉。我有一组我要映射的模型。当我创建会话工厂时,我正在尝试立即执行所有映射。我没有使用自动映射(尽管如果我想要做的事情最终会比它应该更痛苦)。我遇到的问题是,似乎只有顶级地图正在采取。鉴于下面的代码片段并运行单元测试试图保存'bar',它失败并检查日志我看到NHibernate试图将一个条实体保存到foo表。虽然我怀疑它是我的映射,但它可能是我忽略的其他东西。
创建会话工厂的代码(注意我还尝试过单独调用.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);
}
答案 0 :(得分:2)
你做错了。 :)
首先,m.FluentMappings.AddFromAssemblyOf<FooMap>()
和m.FluentMappings.AddFromAssemblyOf<BarMap>()
执行完全相同的操作(如果FooMap
和BarMap
在同一个程序集中)。每个人都告诉Fluent NHibernate扫描包含泛型类型的程序集;因此,如果两个类型都在同一个程序集中,它将扫描两次。
其次,Conventions
调用的范围不是您之后调用的特定程序集,而是整个映射集。所以你要做的是提供两个约定来将表名设置为显式值,第二个是要应用的最后一个。你想要做的是使用x
参数(这是实体类型)并从中创建你的表名。
你需要的是这样的东西:
.Mappings(m =>
{
m.FluentMappings.AddFromAssemblyOf<FooMap>()
.Conventions.Add(Table.Is(x => x.Name + "s"));
})
显然我的实现很幼稚,根据你的表命名约定,你可能想要使用复数(我相信Castle有一个,但是用google找一个并不难)。
您可以在conventions上阅读有关Fluent NHibernate wiki的更多信息。
答案 1 :(得分:0)
使用classmap,您可以在mapping中指定表名。如果未指定,则它将与实体类名称相同。
class FooMap : ClassMap<Foo>
{
public FooMap()
{
Table("foos");
}
}
Conventions适用于所有映射。当您添加了2个表名约定时,只有1个会生效。
你的FooMap和BarMap在同一个程序集中吗?您只需要添加一次组件。
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<FooMap>())
答案 2 :(得分:0)
只想分享这个会自动添加基于结尾字母表的复数名称 s,es,ies。不太确定语法和一些例外,但这对我来说似乎没问题。任何使用Table("foos")
的例外都像@Lachlan Roche说的那样。例如。 客户类会有客户表,类别类会有类别表。
修改后的@James Gregory回答:
.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";
}