本文共 4594 字,大约阅读时间需要 15 分钟。
ABP可以使用任何ORM框架工作,并且已经内置了NHibernate集成。这篇文章会解释如何在ABP中使用NHibernate。阅读本文的前提是假设你已经熟悉了EF的基本知识。
在ABP中使用NH作为ORM的Nuget包是Abp.NHibernate。你应该将它添加到应用程序中。最好在应用程序中分离的程序集(dll)中实现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()); }}
AbpNHibernate模块为了使ABP能够使用NHibernate工作提供了基本的功能和适配器。
在下面的样例配置中,使用了当前程序集中的所有映射类进行了流畅地映射。一个映射类的例子如下所示:
public class TaskMap : EntityMap{ 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 ().Not.Nullable(); Map(x => x.Privacy).CustomType ().Not.Nullable(); Map(x => x.State).CustomType ().Not.Nullable(); }}
EntityMap是ABP继承了 ClassMap的一个类,它会自动映射 Id属性并在构造函数中获得表名。因此,我们可以从它派生并使用映射其他的属性。当然,你可以直接从ClassMap派生,可以使用FluentNHibernate的所有API,也可以使用NHinernate其他的映射技术(比如映射XML文件)。
你可以使用仓储的默认实现而不用在项目中创建仓储类。或者可以创建派生自NhRepositoryBase的仓储类。
虽然可以从ABP的NhRepositoryBase中派生仓储类,但是最佳实践是创建自己的继承了NhRepositoryBase的基类。这样,我们就可以轻松地将一些公用的方法添加到仓储中了。例子如下:
//所有仓储的基类public abstract class MyRepositoryBase: NhRepositoryBase where TEntity : class, IEntity { protected MyRepositoryBase(ISessionProvider sessionProvider) : base(sessionProvider) { } //为所有的仓储添加一些公共的方法}//Id为整数的实体的快捷方式public abstract class MyRepositoryBase : MyRepositoryBase where TEntity : class, IEntity { protected MyRepositoryBase(ISessionProvider sessionProvider) : base(sessionProvider) { } //不要在这里添加任何方法,在上面的方法中添加(因为该方法继承了上面的方法)}public class TaskRepository : MyRepositoryBase , ITaskRepository{ public TaskRepository(ISessionProvider sessionProvider) : base(sessionProvider) { } //这里添加一些task仓储特有的方法}
你不需要为实体类创建仓储,只需要使用预定义的仓储方法。例子:
public class PersonAppService : IPersonAppService{ private readonly IRepository_personRepository; public PersonAppService(IRepository personRepository) { _personRepository = personRepository; } public void CreatePerson(CreatePersonInput input) { person = new Person { Name = input.Name, EmailAddress = input.EmailAddress }; _personRepository.Insert(person); }}
PersonAppService通过构造函数注入了IRepository并使用仓储中的Insert方法。使用这种方法,你可以轻松地注入IRepository(或者IRepository),然后使用预定义的方法。所有预定义的方法列表,请查看。,tprimarykey>
如果你想添加一些自定义的方法,那么首先应该给它添加仓储接口(这是最佳实践),然后在仓储类中实现。ABP提供了一个基类NhRepositoryBase来轻松地实现仓储。要实现仓储接口,只需要从仓储基类中派生仓储就可以了。
假设我们有一个Task(任务)实体,该任务可以派给一个Person(人)实体,而且Task实体有这么几种状态,包括new,assigned,completed等等。我们可能需要写一个自定义方法来根据一些条件和AssignedPerson来获取任务的列表。看下面的代码:
public interface ITaskRepository : IRepository{ List GetAllWithPeople(int? assignedPersonId, TaskState? state);}public class TaskRepository : NhRepositoryBase , ITaskRepository{ public TaskRepository(ISessionProvider sessionProvider) : base(sessionProvider) { } public List 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,然后使用给定的参数添加了一些 Where过滤。最后使用 ToList()获得Tasks的列表。
你也可以在仓储方法中使用Session对象来调用NHibernate的全部API。
仓储应该在它的构造函数中获得一个ISessionProvider。这样的话,我们就可以在单元测试中轻松地注入一个伪造的session提供者了。在运行时,ABP会自动地注入正确的session提供者。
本文转自tkbSimplest博客园博客,原文链接:http://www.cnblogs.com/farb/p/ABPNHibernate.html,如需转载请自行联系原作者