Ich versuche, das Repository-Muster, Ninject für DI mit flüssigem Nhibernate zu verwenden.Wie richte ich mein Repository mit flüssigem Nhibernate ein?
ich meine Lösung in drei Projekte aufgeteilt
web ui - controllers,view (I am using asp.net mvc 2.0)
framework - repository, domain, fluent mapping
tests - where my unit tests will go.
So habe ich Setup diese auf.
Global.aspx
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
}
Also habe ich in meiner Anwendung Start ninject Controller Factory zu verwenden.
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();
}
}
}
Hier habe ich mein Setup ninject Sachen. Ich habe eine Methode entwickelt, die fließend funktioniert. Wie ich es verstehe, sollte dies nur einmal pro Web-Anfrage geschehen (was ich denke, da dies nur beim Start der Anwendung ruft)
Ich bin mir nicht sicher, ob meine GetSessionFactory-Methode sollte statisch sein.
Ich binde dann meine IUsers-Schnittstelle zu meinem UserRepo und übergeben ein Konstruktorargument. Ich vermute, dass meine Repos die Sitzung von Nhibernate brauchen, um etwas zu tun. Also war ich mir nicht sicher, wie ich es an meine Repos weitergeben sollte.
Ich denke, was ich habe könnte falsch sein, wie jedes Repository würde es auf Konfiguration bekommen?
Repository
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();
}
}
Ich habe versucht, ein Repository zu machen, aber wieder bin ich nicht sicher, wie es mit der Sitzung zu tun. Ich muss es öffnen und die Transaktion beginnen. Ich bin mir nicht sicher, ob das woanders gemacht werden sollte.
Ich war auch nicht sicher, ob ich es entsorgen sollte, nachdem es die Methoden durchläuft. Ich habe gesehen, dass Leute Methoden im application_end() entsorgen.
My Home Controller
private IUsers usersRepository;
public HomeController(IUsers usersRepository)
{
this.usersRepository = usersRepository;
}
public ActionResult Index()
{
Users test = new Users()
{
OpenIdIdentifier = "123",
Email = "[email protected]",
};
usersRepository.CreateUser(test);
return View();
}
Schließlich habe ich nur ein Dummy-Controller, einen Dummy-Benutzer erstellt und fügt es in der db. Es funktioniert, aber wie ich schon sagte, der Sitzungsteil verwirrt mich, da ich nicht sicher bin, wie ich es weitergeben soll.
bearbeiten
Dies ist, was ich mit so weit gekommen sind. Es ist immer noch nicht das, was ich will (ich habe eher eine Sitzung pro Anfrage), aber es scheint zu funktionieren.
Ninject Fabrik
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;
}
Ich habe eine if-Anweisung zu prüfen, ob die Sitzung gestartet wird oder nicht. Dies sollte also das Problem beheben, dass jedes Mal SessionFactory gestartet wird.
Mein Repo sieht wie folgt aus
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();
}
}
}
So in jeder Methode, die ich überprüfen, ob eine Sitzung geöffnet ist, wenn nicht, dann ich eine durch diese Methode öffnen.
public static ISession OpenIfClosed(ISessionFactory session, ISession openSession)
{
if (openSession.IsOpen == false)
{
return session.OpenSession();
}
return openSession;
}
Wie gesagt würde ich diese Methode zu erhalten Liebe zu befreien, aber ich bin nicht sicher, wie die Sitzung zu dem repos dann über zu bekommen. Also, bis mir jemand zeigen kann, muss ich es jetzt wohl so machen.
Hmm, Nun zuerst mit dem Ikernal nicht in der Steuerung. Ich folgte, wo der Autor von pro asp.net mvc 2.0 ihre setzen. Ich bin mir bewusst, SessionFactory ist teuer zu erstellen. Ich dachte, indem ich es in den application_start legte, war es ein guter Platz, da es nur einmal erstellt werden sollte. Ich bin auch verwirrt, wo all dieser Code läuft, geht das in Ihrem Webui-Projekt? Wäre es möglich, ein sehr einfaches Projekt zu sehen, damit ich es mit dem Debugger durchgehen kann. Zum Beispiel sehe ich nicht, wo oder wie das Repository nach der ISession im Konstruktor fragt. – chobo2