使用 NHibernate:3.3.2 流畅的 NHibernate:1.3.0 .NET 4.0
大家好,我正在尝试使用自动映射为 Fluent NHibernate 组合一个(非常)简单的参考项目,特别是设置每个层次结构的表继承。我已经尝试从现有(工作)项目中复制配置,并且我已经浏览了 Fluent Wiki 页面上关于 AutoMapping 和继承的示例,并且都给了我相同的结果;我用每层级表设置的基类被视为普通类。
域模型如下所示:
namespace Tests
{
public abstract class Animal
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual int Legs { get; set; }
}
public class Cat : Animal {}
public class Budgie : Animal {}
}
就像我说的,简单,只是为了说明继承。我知道“腿”可能应该在基类上被覆盖:)
AutoMapping 配置如下所示:
public class AutoMappingConfig : DefaultAutomappingConfiguration
{
public override bool ShouldMap(Type type)
{
var include = type.IsSubclassOf(typeof(Animal));
Debug.WriteLineIf(include, string.Format("Included {0} in NHibernate mapping.", type));
return include;
}
public override bool IsDiscriminated(Type type)
{
var result = type.In(
(typeof(Cat)),
(typeof(Budgie))
);
return result;
}
}
最后,配置/会话创建如下所示:
public static ISession NewSession()
{
var cfg = new AutoMappingConfig();
var map = AutoMap.AssemblyOf<Animal>(cfg)
.IgnoreBase<Animal>();
var dbConfiguration = MsSqlConfiguration.MsSql2008
.ConnectionString(ConfigurationManager.ConnectionStrings["testdb"].ConnectionString);
return Fluently.Configure()
.Mappings(m =>m.AutoMappings.Add(map))
.Database(dbConfiguration)
.BuildSessionFactory()
.OpenSession();
}
综上所述,我尝试创建一些新记录:
[Test]
public void CreateData()
{
var tiddles = new Cat {Name = "Tiddles", Legs = 4};
var kylie = new Budgie {Name = "Kylie", Legs = 2};
using (var transaction = _session.BeginTransaction())
{
_session.Save(tiddles); // exception!
_session.Save(kylie);
transaction.Commit();
}
}
}
错误是:
NHibernate.Exceptions.GenericADOException :无法插入:[Tests.Cat] [SQL:INSERT INTO [Cat](名称,腿)值(?,?); 选择 SCOPE_IDENTITY()] ----> System.Data.SqlClient.SqlException:无效的对象名称“猫”。
需要注意的几点:
- 这 '?' 如果我使用 SQL Profiler 检查,则正在填写。
- 当我在 IsDiscriminated(Type type) 方法中放置断点时,我可以看到它被两种预期类型(Cat & Budgie)调用并且每次都返回 true。但是,SQL 正在写入错误的表,并且它没有写入鉴别器列。即,即使它被告知这些班级受到歧视,他们也没有被这样对待。
- 在表中,Id 列是一个自增标识列。
- 我尝试将其他属性添加到两个子类中,以防它们需要除基本属性之外的其他东西来触发正确的行为(没有区别)。
任何帮助将不胜感激。我现在确信它是显而易见的,但这里没有人对 NHibernate 了解很多(LightSpeed 是另一回事)所以我不知道是什么。
好的,所以最终的工作代码如下所示:
public class AutoMappingConfig : DefaultAutomappingConfiguration
{
public override bool ShouldMap(Type type)
{
var include = type.IsSubclassOf(typeof(Animal)) || type == typeof (Animal);
Debug.WriteLineIf(include, string.Format("Included {0} in NHibernate mapping.", type));
return include;
}
public override bool IsDiscriminated(Type type)
{
return typeof(Animal).IsAssignableFrom(type);
}
}
public static ISession NewSession()
{
var cfg = new AutoMappingConfig();
var map = AutoMap.AssemblyOf<Animal>(cfg)
.IncludeBase<Animal>();
var dbConfiguration = MsSqlConfiguration.MsSql2008
.ConnectionString(ConfigurationManager.ConnectionStrings["testdb"].ConnectionString);
return Fluently.Configure()
.Mappings(m =>m.AutoMappings.Add(map))
.Database(dbConfiguration)
.BuildSessionFactory()
.OpenSession();
}
世界一切都很好:)
(即有三个错误)
这里的说明有点令人困惑,因为它首先谈到使用 .IgnoreBase<> 所以 NHibernate 不会将基础本身视为实体,然后在使用抽象层超类型时提到使用 .Includebase<>。我都试过了,但没有 Firo 的回答就没有运气。