首页 > 代码库 > ABP官方文档翻译 9.3 NHibernate集成

ABP官方文档翻译 9.3 NHibernate集成

NHibernate集成

  • Nuget包
  • 配置
    • 实体映射
  • 仓储
    • 默认实现
    • 自定义仓储
      • 应用程序特定基础仓储类

  ABP可以使用任何ORM框架,它内置集成NHibernate。此文档将讲解ABP如何使用NHibernate,假定你对NHibernate已经有了一定的了解。

Nuget包

  在ABP中实现NHibernate做为ORM框架的Nuget包为Abp.NHibernate。你需要在应用程序中添加它。最好在一个单独的程序集中实现NHibernate并在这个程序集里依赖Abp.NHibernate包。

配置

  为了使用NHibernate,你需要在模块的PreInitialize方法中配置它:

[DependsOn(typeof(AbpNHibernateModule))]public class SimpleTaskSystemDataModule : AbpModule{    public override void PreInitialize()    {        var connStr = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;        Configuration.Modules.AbpNHibernate().FluentConfiguration            .Database(MsSqlConfiguration.MsSql2008.ConnectionString(connStr))            .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly()));    }    public override void Initialize()    {        IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());    }}

  AbpNHibernateModule模块为使用NHibernate提供了基础功能和适配器。

实体映射

  在上面的配置示例中,我们在当前程序集中使用所有映射类进行映射。一个映射类示例如下所示:

public class TaskMap : EntityMap<Task>{    public TaskMap()        : base("TeTasks")    {        References(x => x.AssignedUser).Column("AssignedUserId").LazyLoad();        Map(x => x.Title).Not.Nullable();        Map(x => x.Description).Nullable();        Map(x => x.Priority).CustomType<TaskPriority>().Not.Nullable();        Map(x => x.Privacy).CustomType<TaskPrivacy>().Not.Nullable();        Map(x => x.State).CustomType<TaskState>().Not.Nullable();    }}

  EntityMap是ABP的一个扩展了ClassMap<T>的类,它自动映射Id属性并在构造函数中获取表名。所以,我从它继承并使用FluentNHibernate映射其他属性。当然,你可以直接从ClassMap继承,这样就可以使用FluentNHibernate的所有API和NHibernate的其他映射技术(如映射XML文件)。

仓储

  仓储用于从高层抽象数据访问。参见仓储文档了解更多。

默认实现

  在应用程序中,Abp.NHibernate包为实体实现了默认仓储。所以你不需要为实体创建仓储类就可以使用预定义的仓储方法。示例:

public class PersonAppService : IPersonAppService{    private readonly IRepository<Person> _personRepository;    public PersonAppService(IRepository<Person> personRepository)    {        _personRepository = personRepository;    }    public void CreatePerson(CreatePersonInput input)    {                person = new Person { Name = input.Name, EmailAddress = input.EmailAddress };        _personRepository.Insert(person);    }}

  PersonAppService构造注入了IRepository<Person>并使用了Insert方法。使用这种方式,你可以简单的注入IRepository<TEntity>(或IRepository<TEntity,TPrimaryKey>)并使用预定义的方法。参见仓储文档了解所有的预定义方法。

自定义仓储

  如果你想添加一些自定义方法,首先需要添加一个仓储接口(作为最佳实践),然后在一个仓储类中实现它。ABP提供了一个基础类NhRepositoryBase来简单的实现仓储。为了实现IRepository接口,你的仓储类可以仅从这个类继承。

  假定我们有一个Task实体,它可以分配给一个Person(实体)并且Task有一个State(new,assigned,completed...等等)。我们需要写一个自定义方法来基于一些条件来获取任务列表并基于AssignedPerson属性预获取数据,这两个操作在一个数据库查询完成。参见下面示例代码:

public interface ITaskRepository : IRepository<Task, long>{    List<Task> GetAllWithPeople(int? assignedPersonId, TaskState? state);}public class TaskRepository : NhRepositoryBase<Task, long>, ITaskRepository{    public TaskRepository(ISessionProvider sessionProvider)        : base(sessionProvider)    {    }    public List<Task> GetAllWithPeople(int? assignedPersonId, TaskState? state)    {        var query = GetAll();        if (assignedPersonId.HasValue)        {            query = query.Where(task => task.AssignedPerson.Id == assignedPersonId.Value);        }        if (state.HasValue)        {            query = query.Where(task => task.State == state);        }        return query            .OrderByDescending(task => task.CreationTime)            .Fetch(task => task.AssignedPerson)            .ToList();    }}

  GetAll()返回IQueryable<Task>,然后我们可以使用给定的参数添加一些Where过滤器。最终,我们调用ToList()方法来获取任务列表。

  你可以在仓储方法中使用Session对象来使用NHibernate的所有API。

  注意:对于分层应用,在domain/core层定义自定义仓储接口,在NHibernate工程中实现它。这样,你就可以在任何工程中注入这个接口而不用引用NH。

应用程序特定基础仓储类

  尽管你可以从ABP的NhRepositoryBase类继承你的仓储,但是创建自己的基础类并扩展NhRepositoryBase才是最佳实践。这样,你就可以轻松的在自己的仓储中添加shared/common方法。示例:

//Base class for all repositories in my applicationpublic abstract class MyRepositoryBase<TEntity, TPrimaryKey> : NhRepositoryBase<TEntity, TPrimaryKey>    where TEntity : class, IEntity<TPrimaryKey>{    protected MyRepositoryBase(ISessionProvider sessionProvider)        : base(sessionProvider)    {    }    //add common methods for all repositories}//A shortcut for entities those have integer Id.public abstract class MyRepositoryBase<TEntity> : MyRepositoryBase<TEntity, int>    where TEntity : class, IEntity<int>{    protected MyRepositoryBase(ISessionProvider sessionProvider)        : base(sessionProvider)    {    }    //do not add any method here, add the class above (since this inherits it)}public class TaskRepository : MyRepositoryBase<Task>, ITaskRepository{    public TaskRepository(ISessionProvider sessionProvider)        : base(sessionProvider)    {    }    //Specific methods for task repository}

 

返回主目录

ABP官方文档翻译 9.3 NHibernate集成