Я играю с 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 ("Тип") я получил все это в одной таблице.Я также должен был отобразить базовый класс при отображении моего подкласса при создании фабрики сеансов.
Можно ли сказать, что у меня будут только экземпляры расширенного класса, и я сохраню все данные в одной таблице без DisciminateSubClassesOnColumn ?
Редактировать 2
Получил работу, как я хотел, используя UseUnionSubclassForInheritanceMapping (); я получаюбазовый класс работает, как я хочу, и даже если я добавлю расширенный объект и тем самым расширю мою базу данных с помощью дополнительного поля электронной почты, я все равно смогу получить все экземпляры как базовый объект и даже получить все экземпляры как расширенный класс.