gpt4 book ai didi

.net - 需要一个简单的使用nhibernate + 工作单元+ 存储库模式+ 服务层+ ninject 的例子

转载 作者:行者123 更新时间:2023-12-03 14:22:34 28 4
gpt4 key购买 nike

我在用

  • nhibernate + 流畅的 nhibernate
  • asp.net mvc 3
  • 忍者

  • 目前我正在使用带有存储库模式和服务层的 nhibernate、ninject。

    所以我有这个

    注入(inject)
     public class NhibernateSessionFactory
    {
    public ISessionFactory GetSessionFactory()
    {
    ISessionFactory fluentConfiguration = Fluently.Configure()
    .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("ConnectionString")))
    .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Framework.Data.Mapping.TableAMap>().Conventions.Add(ForeignKey.EndsWith("Id")))
    .ExposeConfiguration(cfg => cfg.SetProperty("adonet.batch_size", "20"))
    .ExposeConfiguration(c => c.SetProperty("generate_statistics", "true"))
    //.ExposeConfiguration(BuidSchema)
    .BuildSessionFactory();

    return fluentConfiguration;
    }

    private static void BuidSchema(NHibernate.Cfg.Configuration config)
    {
    new NHibernate.Tool.hbm2ddl.SchemaExport(config).Create(false, true);
    }


    public class NhibernateSessionFactoryProvider : Provider<ISessionFactory>
    {
    protected override ISessionFactory CreateInstance(IContext context)
    {
    var sessionFactory = new NhibernateSessionFactory();
    return sessionFactory.GetSessionFactory();
    }
    }


    public class NhibernateModule : NinjectModule
    {
    public override void Load()
    {
    Bind<ISessionFactory>().ToProvider<NhibernateSessionFactoryProvider>().InSingletonScope();
    Bind<ISession>().ToMethod(context => context.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope()
    .OnActivation(StartTransaction)
    .OnDeactivation(CommitTransaction);
    }

    public void CommitTransaction(ISession session)
    {

    if (session.Transaction.IsActive)
    {
    session.Transaction.Commit();
    }

    }

    public void StartTransaction(ISession session)
    {
    if (!session.Transaction.IsActive)
    {
    session.BeginTransaction();
    }
    }
    }

    因此,我在应用程序的整个生命周期中创建了一次休眠 session 工厂,然后在需要时使用它给我 session 。

    一个交易开始 我开始交易,最后我关闭交易。

    我这样做的原因是因为当我使用 nhibernate profiler 时,我会收到很多关于使用 implicit transactions 的警告。这个问题)。

    一个示例 repo
     public class CalendarRepo : ICalendarRepo
    {
    private readonly ISession session;

    public CalendarRepo(ISession session)
    {
    this.session = session;
    }

    public List<CalendarAppointment> RepeatingAppointments(int repeatingId)
    {

    List<CalendarAppointment> calendarAppointments = session.Query<CalendarAppointment>().Where(x => x.RepeatingId == repeatingId && x.RepeatingId != 0)
    .Take(QueryLimits.Appointments)
    .ToList();
    return calendarAppointments;

    }
    }

    服务层
     public class CalendarService : ICalendarService
    {
    private readonly ICalendarRepo calendarRepo;


    public CalendarService(ICalendarRepo calendarRepo)
    {
    this.calendarRepo = calendarRepo;


    }
    // normally would return something and take in params
    public void SampleServiceMethod()
    {
    // do some checks if needed
    // call up the repository
    // call commit
    // done.
    }
    }

    所以这基本上就是我所拥有的。

    我想使用工作单元模式,这样我就可以提交更多的事情并正确处理事务( as right now I been told that I am doing them not quite right)

    所以我正在寻找一个简单的例子来说明如何让他们一起工作,并找出我需要改变多少我到目前为止所得到的东西。

    我看到的大多数教程都比我想的要复杂。大多数人做 TDD 并制作通用存储库什么是好的,但在我进入那个阶段之前,我希望看到一个教程,即使它是重复代码,它也能简单地做事。

    编辑

    所以我一直在玩它并想出了这个非常简单的例子。我不确定我是否做得对。

    忍者
    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {

    kernel.Bind<ISessionFactory>().ToProvider<NhibernateSessionFactoryProvider>().InSingletonScope();
    kernel.Bind<ISession>().ToMethod(context => context.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope();
    kernel.Bind<ITable1Repo>().To<Table1Repo>();
    kernel.Bind<ITable1Service>().To<Table1Service>();
    kernel.Bind<IUnitofWork>().To<UnitofWork>();

    }

    nhibernate 工厂类显示在原始帖子中。
     // Controller
    public class Default1Controller : Controller
    {
    private readonly ITable1Service table1Service;
    //
    // GET: /Default1/
    public Default1Controller(ITable1Service table1Service)
    {
    this.table1Service = table1Service;
    }

    public ActionResult Index()
    {
    table1Service.Save();
    return View();
    }

    }

    //域
      public class Table1
    {
    public virtual int Id { get; private set; }
    public virtual string C1 { get; set; }
    public virtual string C2 { get; set; }
    }

    //流利映射
      public class Table1Mapping : ClassMap<Table1>
    {
    public Table1Mapping()
    {
    Id(x => x.Id);
    Map(x => x.C1);
    Map(x => x.C2);
    }
    }

    // repo
     public class Table1Repo : unitofwork.Models.Repository.ITable1Repo
    {
    private readonly ISession session;

    public Table1Repo(ISession session)
    {
    this.session = session;
    }

    public void Create(Table1 tbl1)
    {
    session.Save(tbl1);
    }
    }

    //服务层
     public class Table1Service : unitofwork.Models.Service.ITable1Service
    {
    private readonly ITable1Repo table1Repo;
    private readonly IUnitofWork unitOfWork;
    public Table1Service(ITable1Repo table1Repo, IUnitofWork unitOfWork)
    {
    this.table1Repo = table1Repo;
    this.unitOfWork = unitOfWork;
    }

    public void Save()
    {
    Table1 a = new Table1();
    a.C1 = "test";
    a.C2 = "test2";

    table1Repo.Create(a);
    unitOfWork.Commit();


    }
    }

    //工作单元
    public class UnitofWork : unitofwork.Models.IUnitofWork
    {
    private readonly ITransaction transaction;
    private readonly ISession session;

    public UnitofWork(ISession session)
    {
    this.session = session;
    session.FlushMode = FlushMode.Auto;
    transaction = session.BeginTransaction(IsolationLevel.ReadCommitted);
    }

    public void Commit()
    {
    if (!transaction.IsActive)
    {
    throw new InvalidOperationException("Oops! We don't have an active transaction");
    }
    transaction.Commit();
    }

    public void Rollback()
    {
    if (transaction.IsActive)
    {
    transaction.Rollback();
    }
    }

    public void Dispose()
    {
    if (session.IsOpen)
    {
    session.Close();
    }
    }
    }

    最佳答案

    我使用的是'vanilla' ASP.NET,而不是 ASP.NET MVC 3,但本质上我们正在做同样的事情。

    首先,我有一个单独的 UnitOfWork像这样的类:

    public class UnitOfWork
    {
    private static ISessionFactory SessionFactory
    {
    get
    {
    return Container.Get<ISessionFactory>();
    }
    }

    public static ISession Session
    {
    get
    {
    return SessionFactory.GetCurrentSession();
    }
    }

    public static void Start()
    {
    CurrentSessionContext.Bind(SessionFactory.OpenSession());
    Session.FlushMode = FlushMode.Commit;
    Session.BeginTransaction(IsolationLevel.ReadCommitted);
    }

    public static void Rollback()
    {
    Rollback(true);
    }

    /// <summary>
    /// Rollback the current transaction, and optionally start a new transaction
    /// </summary>
    /// <param name="startNew">Whether to start a new transaction and keep the session open</param>
    public static void Rollback(bool startNew)
    {
    ISession session = CurrentSessionContext.Unbind(SessionFactory);

    if (session != null)
    {
    // Rollback current transaction
    if (session.Transaction.IsActive && !session.Transaction.WasRolledBack)
    {
    session.Transaction.Rollback();
    }

    // Close and discard the current session
    session.Close();
    session.Dispose();
    session = null;
    }

    if (startNew)
    {
    Start();
    }
    }

    /// <summary>
    /// Commit the current transaction, keeping the current session open and starting a new transaction
    ///
    /// Call Commit multiple times during a single unit of work if you want to commit database changes in
    /// multiple transactions
    /// </summary>
    public static void Commit()
    {
    Commit(true);
    }

    /// <summary>
    /// Commit the current transaction, and optionally keep the session open and start a new transaction
    ///
    /// Call Commit multiple times during a single unit of work if you want to commit database changes in
    /// multiple transactions
    /// </summary>
    /// <param name="startNew">Whether to start a new transaction and keep the session open</param>
    public static void Commit(bool startNew)
    {
    if (startNew)
    {
    Session.Transaction.Commit();
    Session.BeginTransaction(IsolationLevel.ReadCommitted);
    }
    else
    {
    ISession session = CurrentSessionContext.Unbind(SessionFactory);

    if (session != null)
    {
    if (session.Transaction.IsActive && !session.Transaction.WasRolledBack)
    {
    session.Transaction.Commit();
    }

    session.Close();
    session.Dispose();
    session = null;
    }
    }
    }
    }

    我使用 HTTP 模块为每个 Web 请求启动一个新的工作单元,并自动提交/回滚。不确定在使用 ASP.NET MVC 3 时是否需要 HTTP 模块,或者是否有其他方法。无论如何,相关部分如下所示:
    public class IoCHttpModule : IHttpModule, IDisposable
    {
    private HttpApplication httpApplication;

    public void Init(HttpApplication context)
    {
    if (context == null)
    throw new ArgumentException("context");

    this.httpApplication = context;

    this.httpApplication.BeginRequest += new EventHandler(BeginRequest);
    this.httpApplication.EndRequest += new EventHandler(EndRequest);
    this.httpApplication.Error += new EventHandler(Error);

    StandardIoCSetup.Initialise(SessionContextType.Web);
    }

    private void BeginRequest(object sender, EventArgs e)
    {
    UnitOfWork.Start();
    }

    private void EndRequest(object sender, EventArgs e)
    {
    UnitOfWork.Commit(false);
    }

    private void Error(object sender, EventArgs e)
    {
    UnitOfWork.Rollback(false);
    }

    public void Dispose()
    {
    if (this.httpApplication == null)
    return;

    this.httpApplication.Dispose();
    }
    }

    因此,每个 Web 请求都会启动一个新的工作单元,如果没有未处理的异常,则会自动提交。当然也可以手动调用 UnitOfWork.Commit()UnitOfWork.Rollback()如果需要,在 Web 请求中。行 StandardIoCSetup.Initialise...使用 Ninject 模块配置 NHibernate,与您已经在做的非常相似。

    所以从本质上讲,在你已经拥有的东西上添加一个工作单元并不是什么工作。

    关于.net - 需要一个简单的使用nhibernate + 工作单元+ 存储库模式+ 服务层+ ninject 的例子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7113245/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com