使用Fluent NHibernate和数据访问层

时间:2013-10-10 22:43:08

标签: c# asp.net-mvc nhibernate design-patterns fluent-nhibernate

首先介绍一下:我有一个解决方案,其中包含以下3个项目:

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

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

为了使事情变得更复杂,我有一个像这样的继承结构:

    API层中的
  • User object继承自
  • DA层中的
  • User data object继承自
  • DA层中的
  • Data object

Data object负责将对象保存到数据库,因为所有对象的保存功能都相同,我不想重复代码。我遇到的问题是如何使用User objectData object类内部将SessionFactory保存到数据库中,当用户登录网站时我实例化了{{1}}并且可以通过他们的会议。

如果没有明确说明,请告诉我。

2 个答案:

答案 0 :(得分:2)

一种方法是使用DI pattern,例如统一。

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

您的data object也可以是通用的T就是User data object。然后,您可以在data object中实施一种方法,例如使用注入的T

保存,更新,删除IRepository

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初始化应该在MVC项目中的global.asax内完成。您还可以通过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

答案 1 :(得分:0)

您可以使用以下选项:

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

认为会话始终与接口层相关联。