我正在玩nhibernate和fluent-nhibernate。
我想要做的是创建一个具有基本模型/实体的基础,然后能够创建一个与基础一起工作和/或扩展基础的插件。如果我在漫游,我希望通过代码示例清楚。
我有一个装配作为我的角石(底座组件) 在这里,我得到了实体:
public class MemberBase
{
public virtual Guid Id { get; set; }
public virtual string UserName { get; set; }
public virtual string Password { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
}
我得到了流利的映射:
public MemberBaseMap()
{
Id(x => x.Id);
Map(x => x.UserName);
Map(x => x.Password);
Map(x => x.FirstName);
Map(x => x.LastName);
Table("Members");
}
我获得了成员资料库的界面:
public interface IMemberBaseRepository<T>
{
void Add(T m);
void Update(T m);
void Remove(T m);
T Fetch(Guid id);
ICollection<T> List { get; }
}
我甚至为成员提供了基本的存储库:
public class MemberBaseRepository : IMemberBaseRepository<MemberBase>
{
private static ISessionFactory _sessionFactory;
private static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
_sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ShowSql().ConnectionString("Data Source=W7;Initial Catalog=nhibernateDemo;Integrated Security=True"))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<MemberBase>()
//.Conventions.Add(Table.Is(x => "Members"))
)
//.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
return _sessionFactory;
}
}
public void Add(MemberBase m)
{
using (ISession session = SessionFactory.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
session.Save(m);
transaction.Commit();
}
}
public void Update(MemberBase m)
{
using (ISession session = SessionFactory.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
session.Update(m);
transaction.Commit();
}
}
public void Remove(MemberBase m)
{
using (ISession session = SessionFactory.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
session.Delete(m);
transaction.Commit();
}
}
public MemberBase Fetch(Guid id)
{
using (ISession session = SessionFactory.OpenSession())
return session.Get<MemberBase>(id);
}
public ICollection<MemberBase> List
{
get
{
using (ISession session = SessionFactory.OpenSession())
return session.CreateCriteria(typeof(MemberBase)).List<MemberBase>();
}
}
}
这一切都在我的测试中有效,没问题: 这是我的nunit测试:
[TestFixture]
public class MembersBasic
{
private ISessionFactory _sessionFactory;
private FluentConfiguration _configuration;
private IMemberBaseRepository<MemberBase> _repository;
private IMemberBaseRepository<MemberBase> Repository
{
get
{
if (_repository == null)
_repository = new MemberBaseRepository();
return _repository;
}
}
#region Test Data
private readonly MemberBase[] _members = new[]
{
new MemberBase { FirstName = "Daisy", LastName = "Harrison" },
new MemberBase { FirstName = "Jack", LastName = "Torrance" },
new MemberBase { FirstName = "Sue", LastName = "Wilkters" },
new MemberBase { FirstName = "Bill", LastName = "Taft" },
new MemberBase { FirstName = "Joan", LastName = "Pope" }
};
private void CreateInitialData()
{
using (ISession session = _sessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
foreach (var m in _members)
session.Save(m);
transaction.Commit();
}
}
}
#endregion
private bool IsInCollection(MemberBase m, ICollection<MemberBase> collection)
{
foreach (var item in collection)
if (m.Id == item.Id)
return true;
return false;
}
//[TestFixtureSetUp]
//public void TestFixtureSetup()
//{
//}
[SetUp]
public void Setup()
{
_configuration = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ShowSql().ConnectionString("Data Source=localhost;Initial Catalog=nhibernateDemo;Integrated Security=True"))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<MemberBase>()
//.Conventions.Add(Table.Is(x=> "Members"))
)
.ExposeConfiguration(cfg =>
{
new SchemaExport(cfg).Create(false, true);
});
_sessionFactory = _configuration.BuildSessionFactory();
CreateInitialData();
}
[Test]
public void Can_add_member()
{
var member = new MemberBase { FirstName = "John", LastName = "Doe" };
Repository.Add(member);
using (ISession session = _sessionFactory.OpenSession())
{
var fromDB = session.Get<MemberBase>(member.Id);
Assert.IsNotNull(fromDB);
Assert.AreNotSame(member, fromDB);
Assert.AreEqual(member.FirstName, fromDB.FirstName);
Assert.AreEqual(member.LastName, fromDB.LastName);
}
}
[Test]
public void Can_update_member()
{
var member = _members[0];
member.FirstName = "John";
member.LastName = "Doe";
Repository.Update(member);
using (ISession session = _sessionFactory.OpenSession())
{
var fromDB = session.Get<MemberBase>(member.Id);
Assert.AreEqual(member.FirstName, fromDB.FirstName);
Assert.AreEqual(member.LastName, fromDB.LastName);
}
}
[Test]
public void Can_remove_member()
{
Repository.Remove(_members[0]);
using (ISession session = _sessionFactory.OpenSession())
{
var fromDB = session.Get<MemberBase>(_members[0].Id);
Assert.IsNull(fromDB);
}
}
[Test]
public void Can_fetch_member()
{
var member = Repository.Fetch(_members[0].Id);
Assert.IsNotNull(member);
Assert.AreEqual(_members[0].Id, member.Id);
Assert.AreEqual(_members[0].FirstName, member.FirstName);
Assert.AreEqual(_members[0].LastName, member.LastName);
}
[Test]
public void Can_list_members()
{
var members = Repository.List;
Assert.IsNotNull(members);
Assert.AreEqual(5, members.Count);
Assert.IsTrue(IsInCollection(_members[0], members));
Assert.IsTrue(IsInCollection(_members[1], members));
Assert.IsTrue(IsInCollection(_members[2], members));
Assert.IsTrue(IsInCollection(_members[3], members));
Assert.IsTrue(IsInCollection(_members[4], members));
}
}
现在我的所有问题都开始了,当我现在在一个新的程序集中创建一个继承基础的成员并获得一个映射器等等以及它自己的存储库。 这是扩展的东西:
public class MemberExt : MemberBase
{
public virtual string Email { get; set; }
}
public class MemberExtMap : SubclassMap<MemberExt>
{
public MemberExtMap()
{
Extends<MemberBase>();
Map(x => x.Email);
Table("Members");
}
}
public class MemberExtRepository : IMemberBaseRepository<MemberExt>
{
private static ISessionFactory _sessionFactory;
private static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
_sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ShowSql().ConnectionString("Data Source=W7;Initial Catalog=nhibernateDemo;Integrated Security=True"))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<MemberExt>()
//.Conventions.Add(Table.Is(x => "Members"))
)
//.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
return _sessionFactory;
}
}
public void Add(MemberExt m)
{
using (ISession session = SessionFactory.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
session.Save(m);
transaction.Commit();
}
}
public void Update(MemberExt m)
{
using (ISession session = SessionFactory.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
session.Update(m);
transaction.Commit();
}
}
public void Remove(MemberExt m)
{
using (ISession session = SessionFactory.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
session.Delete(m);
transaction.Commit();
}
}
public MemberExt Fetch(Guid id)
{
using (ISession session = SessionFactory.OpenSession())
return session.Get<MemberExt>(id);
}
public ICollection<MemberExt> List
{
get
{
using (ISession session = SessionFactory.OpenSession())
return session.CreateCriteria(typeof(MemberExt)).List<MemberExt>();
}
}
}
这应该是我想象的,也许确实如此,但是当我尝试运行我的测试设置时,我得到了错误:
“Test.Extend.Members.MembersExt.Can_add_member: SetUp:NHibernate.MappingException: 没有持久性: Plugin.Ext.Entity.MemberExt“
修改
让事情发挥作用我的错误似乎是我需要为我的子类创建一个不同的表,并且只保存扩展属性。或者当使用 DiscriminateSubClassesOnColumn(“Type”)时,我在同一个表中得到了所有内容。 在构建会话工厂时,我还必须在映射我的子类时映射基类。
是否可以说我只会有扩展类的实例并将所有数据保存在同一个表格中,而不是 DisciminateSubClassesOnColumn ?
修改2
按照我想要的方式工作,使用 UseUnionSubclassForInheritanceMapping(); 我得到基类正常工作,即使我添加了一个扩展对象,并通过它扩展我的数据库额外的电子邮件字段我仍然可以将所有实例作为基础对象,甚至将所有实例作为扩展类。