NHibernate 集成

ASP.NET Boilerplate可以与任何O / RM框架一起使用。它与NHibernate内置集成。本文档将解释如何将NHibernate与ASP.NET Boilerplate一起使用。假设你已经熟悉NHibernate的某些基础知识。

NuGet包

在ASP.NET Boilerplate中使用NHibernate作为O / RM的NuGet包是  Abp.NHibernate您需要将其添加到您的应用程序中。最好在应用程序中的独立程序集(dll)中实现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可以与ASP.NET Boilerplate一起使用。

实体映射

在上面的示例配置中,我们使用当前程序集中的所有映射类流畅地映射。示例映射类可以如下:

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是一个ASP.NET Boilerplate类,它扩展了ClassMap <T>,自动映射Id属性并在构造函数中获取表名。我们从它派生并使用FluentNHibernate映射其他属性如果需要,可以直接从ClassMap派生。您可以使用完整的APIFluentNHibernate,您可以使用其他映射技术,例如映射XML文件。

存储库用于从较高层抽象数据访问。有关 详细信息,请参阅  存储库文档。  

默认实施

该  Abp.NHibernate  NuGet包实现的默认存储库,在应用程序中的实体。您不必为实体创建存储库类,只需使用预定义的存储库方法。例:

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>)并使用预定义的方法。有关 所有预定义方法的列表,请参阅  存储库文档

自定义存储库

如果要添加自定义方法,作为最佳实践,必须先将其添加到存储库接口,然后在存储库类中实现它。ASP.NET Boilerplate提供了一个基类NhRepositoryBase,可以轻松实现存储库。要实现IRepository接口,您只需从此类派生您的存储库。

假设我们有一个可以分配给Person(实体)的Task实体,Task有一个State(new,assign,completed ......等等)。我们可能需要编写一个自定义方法来获取具有某些条件的Tasks列表,并在单个数据库查询中预先获取AssisgnedPerson属性。请参阅示例代码:

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。 

注意:在域/核心层定义自定义存储库接口,在NHibernateproject中为分层应用程序实现它。这样,您可以从任何项目注入接口而无需引用NH。

特定于应用程序的库存储库类

虽然您可以从ASP.NET Boilerplate中的NhRepositoryBase派生您的存储库,但最好还是创建一个扩展NhRepositoryBase的基类。这样,您可以轻松地将共享/公共方法添加到您的存储库。例:

//Base class for all repositories in my application
public 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 that have an 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 methods 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
}

nidie.com.cn - 用心与你沟通