Я пытаюсь использовать шаблон репозитория, предназначенный для DI с беглым nhibernate.
Я разбил свое решение на 3 проекта
web ui - controllers,view (I am using asp.net mvc 2.0)
framework - repository, domain, fluent mapping
tests - where my unit tests will go.
Итак, я настроил это.
Global.aspx
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
}
Итак, я вставил в свое приложение начало использования фабричного контроллера ninject.
NinjectControllerFactory
public class NinjectControllerFactory : DefaultControllerFactory
{
// A Ninject "kernel" is the thing that can supply object instances
private IKernel kernel = new StandardKernel(new T4GDemoSevice());
// ASP.NET MVC calls this to get the controller for each request
protected override IController GetControllerInstance(RequestContext context, Type controllerType)
{
if (controllerType == null)
return null;
return (IController)kernel.Get(controllerType);
}
// Configures how abstract service types are mapped to concrete implementations
private class DemoSevice : NinjectModule
{
public override void Load()
{
Bind<ISessionFactory>().ToMethod(c => GetSessionFactory()).InSingletonScope();
Bind<ISession>().ToMethod(c => c.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope();
Bind<IUsers>().To<UsersRepo>().WithConstructorArgument("session",GetSessionFactory());
}
public static ISessionFactory GetSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("test")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<T4G_Demo.Framework.Data.NhibernateMapping.UserMap>())
.BuildSessionFactory();
}
}
}
Здесь я настраиваю свои вещи. Я сделал метод, который настраивает бегло. Насколько я понимаю, это должно происходить только один раз для каждого веб-запроса (что, я думаю, так и происходит, так как это вызывает только при запуске приложения)
Я не уверен, что мой метод GetSessionFactory должен быть статическим.
Затем я связываю свой интерфейс IUsers с моим UserRepo и передаю аргумент конструктора. Я предполагаю, что моим репам нужен сеанс nhibernate, чтобы что-то сделать. Поэтому я не был уверен, как передать его в мои репозитории.
Я думаю, что я могу ошибаться, так как каждый репозиторий получит свою конфигурацию ??
Репозиторий
public class UsersRepo : IUsers
{
private ISessionFactory session;
public UsersRepo(ISessionFactory session)
{
this.session = session;
}
public void CreateUser(Domain.Users newUser)
{
var openSession = session.OpenSession();
var transaction = openSession.BeginTransaction();
openSession.SaveOrUpdate(newUser);
transaction.Commit();
}
}
Я пытался создать репозиторий, но снова я не уверен, как это сделать с сеансом. Как будто я должен открыть его и начать транзакцию. Я не уверен, должно ли это быть сделано где-то еще.
Я также не был уверен, должен ли я распоряжаться им после того, как он пройдет через методы. Я видел, как люди избавляются от методов в application_end ().
Мой домашний контроллер
private IUsers usersRepository;
public HomeController(IUsers usersRepository)
{
this.usersRepository = usersRepository;
}
public ActionResult Index()
{
Users test = new Users()
{
OpenIdIdentifier = "123",
Email = "as@hotmail.com",
};
usersRepository.CreateUser(test);
return View();
}
Наконец, я просто создал фиктивный контроллер, который создает фиктивного пользователя и вставляет его в базу данных. Это работает, но, как я уже сказал, сессионная часть смущает меня, так как я не уверен, как это передать.
Редактировать
Это то, что я придумал до сих пор. Это все еще не то, что я хочу (у меня есть сеанс на запрос), но, похоже, работает.
Фабрика Ninject
public static ISessionFactory GetSessionFactory()
{
if (session == null)
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("test")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<T4G_Demo.Framework.Data.NhibernateMapping.UserMap>())
//.ExposeConfiguration(BuidSchema)
.BuildSessionFactory();
}
return session;
}
Я добавил оператор if, чтобы проверить, запущен сеанс или нет. Так что это должно решить проблему запуска SessionFactory каждый раз.
Мой репозиторий выглядит так
public class UsersRepo : IUsers
{
private ISession openSession;
private ISessionFactory session;
public UsersRepo(ISessionFactory session)
{
this.openSession = session.OpenSession();
this.session = session;
}
public void CreateUser(Users newUser)
{
openSession = NhibernateUtilities.OpenIfClosed(session, openSession);
openSession.SaveOrUpdate(newUser);
}
public Users GetUser(Guid userId)
{
openSession = NhibernateUtilities.OpenIfClosed(session, openSession);
var query = from b in openSession.Query<Users>()
where b.UserId == userId
select b;
return query.SingleOrDefault();
}
public void DeleteUser(Users user)
{
openSession = NhibernateUtilities.OpenIfClosed(session, openSession);
openSession.Delete(user);
}
public void SaveOrUpdate()
{
using (openSession)
{
using (var transaction = openSession.BeginTransaction())
{
transaction.Commit();
}
}
}
Таким образом, в каждом методе я проверяю, открыт ли сеанс, если нет, то я открываю один с помощью этого метода.
public static ISession OpenIfClosed(ISessionFactory session, ISession openSession)
{
if (openSession.IsOpen == false)
{
return session.OpenSession();
}
return openSession;
}
Как я уже сказал, я бы хотел избавиться от этого метода, но я не уверен, как перенести сеанс в репозитории. Так что, пока кто-то не покажет мне, я думаю, что сейчас я должен сделать это так.