首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >我需要一个使用nhibernate +工作单元+存储库模式+服务层+对象的简单示例

我需要一个使用nhibernate +工作单元+存储库模式+服务层+对象的简单示例
EN

Stack Overflow用户
提问于 2011-08-19 03:48:27
回答 1查看 7.5K关注 0票数 17

我正在使用

fluent nhibernate

  • asp.net mvc 3

  • ninject

+

  • nhibernate

目前我使用的是nhibernate,它包含了存储库模式和服务层。

所以我有这个

九个对象

代码语言:javascript
复制
 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();
            }
        }
    }

因此,我在应用程序的生命周期中创建了一次nhibernate会话工厂,然后在需要时使用它给我会话。

在事务开始时,我启动一个事务,在结束时,我关闭该事务。

我这么做的原因是因为当我使用nhibernate分析器时,我会收到很多关于使用 implicit transactions的警告,这就像是给问题贴了个创可贴,但从来没有真正解决过它(它减少了数量,但任何懒惰的加载仍然会导致这个问题)。

示例存储库

代码语言:javascript
复制
 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;

        }
    }

服务层

代码语言:javascript
复制
 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,并将泛型存储库做得很好,但在我进入那个阶段之前,我希望看到一个教程,即使它是重复代码,也能做到很简单。

编辑

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

对象

代码语言:javascript
复制
/// <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工厂类显示在原始post中。

代码语言:javascript
复制
 // 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();
        }

    }

//域名

代码语言:javascript
复制
  public class Table1
    {
        public virtual int Id { get; private set; }
        public virtual string C1 { get;  set; }
        public virtual string C2 { get; set; }
    }

// Fluent映射

代码语言:javascript
复制
  public class Table1Mapping : ClassMap<Table1>
    {
        public Table1Mapping()
        {
            Id(x => x.Id);
            Map(x => x.C1);
            Map(x => x.C2);
        }
    }

//回购

代码语言:javascript
复制
 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);
        }
    }

//服务层

代码语言:javascript
复制
 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();


        }
    }

//工作单元

代码语言:javascript
复制
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();
            }
        }
    }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-08-19 14:58:05

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

首先,我有一个单独的UnitOfWork类,如下所示:

代码语言:javascript
复制
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 MVC3时是否需要HTTP模块,或者是否有其他方法。无论如何,相关部分如下所示:

代码语言:javascript
复制
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请求都会启动一个新的工作单元,如果没有未处理的异常,则会自动提交。当然,如果需要,您可以在web请求中手动调用UnitOfWork.Commit()UnitOfWork.Rollback()。行StandardIoCSetup.Initialise...使用一个StandardIoCSetup.Initialise...模块来配置NHibernate,这与您已经在做的事情非常相似。

因此,从本质上讲,在已有的基础上添加一个工作单元并不是一件很容易的事情。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7113245

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档