0

首先是一点背景:我有一个解决方案,其中包含以下 3 个项目:

  • MVC 项目(面向用户的网站)
  • API项目(业务逻辑项目)
  • 数据访问项目(NHibernate 所在的项目)

我在 DA 层中有 Fluent 映射,并且(目前)我SessionFactory在 MVC 站点的 GLobal.asax 中构建了 Hibernate。这并不理想,因为我希望 NHibernate 完全包含在 DA 层中,并且 MVC 应用程序只与 API 层通信。另外,我想SessionFactory只构建一次,因为它是一项昂贵的操作。

为了使事情更复杂,我有一个继承结构,如下所示:

  • User object在 API 层继承自
  • User data object在 DA 层继承自
  • Data object在 DA 层。

Data object负责将对象保存到数据库,因为保存功能在所有对象中都是相同的,我不想重复代码。我遇到的问题是如何在使用我在用户登录网站时实例化的并且可以在他们的会话中持续存在的同时User object从类内部保存到数据库中。Data objectSessionFactory

如果有什么没有解释清楚,请告诉我。

4

2 回答 2

3

一种方法是使用DI 模式,例如 Unity。

实现你data object有一个构造函数,例如一个 IRepository 接口。此接口的实现处理 nHibernate 会话工厂...

data object也可以是通用的 where Tis one 例如User data object。然后你实现一个方法data object来保存,更新,删除T注入IRepository

a的伪代码data object

public interface IEntity
{
}

public interface IRepository
{
    ISession Session { get; }
}

public class DataObjectBase<T> where T : IEntity
{
    private IRepository Repository { get; set; }

    public DataObjectBase(IRepository repository)
    {
        this.Repository = repository;
    }

    public T Get(int id)
    {
        return Repository.Session.Get<T>(id);
    }

    public void Save(T value)
    {
        Repository.Session.Save(value);
    }

    public void Update(T value)
    {
        Repository.Session.Update(value);
    }

    public void Delete(T value)
    {
        Repository.Session.Delete(value);
    }

    public IQueryable<T> Query()
    {
        return Repository.Session.Query<T>();
    }
}

特定数据对象的实现

public class ADataObject : IEntity
{
    public int Id { get; set; }

    // [...]
}

为数据对象实现数据上下文

public class ADataObjectContext : DataObjectBase<ADataObject>
{
    public ADataObjectContext(IRepository repository)
        : base(repository)
    {
    }
}

使用 Unity 的简单示例测试

public class Test
{
    public void Run()
    {
        IUnityContainer myContainer = new UnityContainer();
        myContainer.RegisterType<IRepository, NHibernateRepository>();

        var ctx = myContainer.Resolve<ADataObjectContext>();

        var obj = ctx.Query().Where(p => p.Id == 2);
    }
}

当然,您必须实施NHibernateRespository才能做任何您想做的事情。

UnityContainer初始化应该在您的global.asaxMVC 项目中完成。您还可以通过 web.config 配置 Unity。

NHibernateRespository实际上应该是一个单例。这可以由您实现,或者您只需使用 Unity 功能将您的类型实例化为单例。new ContainerControlledLifetimeManager()正是这样做的。

除了将会话公开为属性之外,您还可以公开一个打开新会话的方法。或者您实现一个开始和结束工作单元,这是 Web 环境中的常见做法......

正常存储库模式、工作单元、统一性的其他链接......或者只是在 Google 上搜索 nhibernate 存储库模式

http://slynetblog.blogspot.de/2011/11/in-spite-of-common-now-approach-of.html

http://blog.bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/

http://msdn.microsoft.com/en-us/library/dd203101.aspx

于 2013-10-11T20:41:18.440 回答
0

您可以使用以下选项:

  • 使用 AOP:当 API 层调用函数时,AOP 会创建一个会话,并将方法或构造函数中的值参数传递给 DA 层。
  • 从 MVC 项目到 DA 层,它通过所有层将会话传递到 DA 层,并在方法或构造函数中使用参数。

认为会话总是与接口层相关联。

于 2013-10-11T07:57:36.023 回答