ABP理论学习之NHibernate集成

简介:

本篇目录

ABP可以使用任何ORM框架工作,并且已经内置了NHibernate集成。这篇文章会解释如何在ABP中使用NHibernate。阅读本文的前提是假设你已经熟悉了EF的基本知识。

Nuget包

在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<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的一个类,它会自动映射 Id属性并在构造函数中获得表名。因此,我们可以从它派生并使用FluentNHibernate映射其他的属性。当然,你可以直接从ClassMap派生,可以使用FluentNHibernate的所有API,也可以使用NHinernate其他的映射技术(比如映射XML文件)。

仓储

你可以使用仓储的默认实现而不用在项目中创建仓储类。或者可以创建派生自NhRepositoryBase的仓储类。

仓储基类

虽然可以从ABP的NhRepositoryBase中派生仓储类,但是最佳实践是创建自己的继承了NhRepositoryBase的基类。这样,我们就可以轻松地将一些公用的方法添加到仓储中了。例子如下:

//所有仓储的基类
public abstract class MyRepositoryBase<TEntity, TPrimaryKey> : NhRepositoryBase<TEntity, TPrimaryKey>
    where TEntity : class, IEntity<TPrimaryKey>
{
    protected MyRepositoryBase(ISessionProvider sessionProvider)
        : base(sessionProvider)
    {
    }

    //为所有的仓储添加一些公共的方法
}

//Id为整数的实体的快捷方式
public abstract class MyRepositoryBase<TEntity> : MyRepositoryBase<TEntity, int>
    where TEntity : class, IEntity<int>
{
    protected MyRepositoryBase(ISessionProvider sessionProvider)
        : base(sessionProvider)
    {
    }

    //不要在这里添加任何方法,在上面的方法中添加(因为该方法继承了上面的方法)
}

public class TaskRepository : MyRepositoryBase<Task>, ITaskRepository
{
    public TaskRepository(ISessionProvider sessionProvider)
        : base(sessionProvider)
    {
    }

    //这里添加一些task仓储特有的方法
}

默认实现

你不需要为实体类创建仓储,只需要使用预定义的仓储方法。例子:

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并使用仓储中的Insert方法。使用这种方法,你可以轻松地注入IRepository(或者IRepository),然后使用预定义的方法。所有预定义的方法列表,请查看仓储文档。,tprimarykey>

自定义仓储方法

如果你想添加一些自定义的方法,那么首先应该给它添加仓储接口(这是最佳实践),然后在仓储类中实现。ABP提供了一个基类NhRepositoryBase来轻松地实现仓储。要实现仓储接口,只需要从仓储基类中派生仓储就可以了。

假设我们有一个Task(任务)实体,该任务可以派给一个Person(人)实体,而且Task实体有这么几种状态,包括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,然后使用给定的参数添加了一些 Where过滤。最后使用 ToList()获得Tasks的列表。

你也可以在仓储方法中使用Session对象来调用NHibernate的全部API。

仓储应该在它的构造函数中获得一个ISessionProvider。这样的话,我们就可以在单元测试中轻松地注入一个伪造的session提供者了。在运行时,ABP会自动地注入正确的session提供者。




本文转自tkbSimplest博客园博客,原文链接:http://www.cnblogs.com/farb/p/ABPNHibernate.html,如需转载请自行联系原作者

目录
相关文章
|
26天前
|
测试技术
软件质量保护与测试(第2版)学习总结第十三章 集成测试
本文是《软件质量保护与测试》(第2版)第十三章的学习总结,介绍了集成测试的概念、主要任务、测试层次与原则,以及集成测试的不同策略,包括非渐增式集成和渐增式集成(自顶向下和自底向上),并通过图示详细解释了集成测试的过程。
46 1
软件质量保护与测试(第2版)学习总结第十三章 集成测试
|
18天前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
39 1
|
18天前
|
Java Spring
springboot 学习十一:Spring Boot 优雅的集成 Lombok
这篇文章是关于如何在Spring Boot项目中集成Lombok,以简化JavaBean的编写,避免冗余代码,并提供了相关的配置步骤和常用注解的介绍。
62 0
|
18天前
|
机器学习/深度学习 算法 前端开发
集成学习任务七和八、投票法与bagging学习
集成学习任务七和八、投票法与bagging学习
11 0
|
25天前
|
机器学习/深度学习 算法
【机器学习】迅速了解什么是集成学习
【机器学习】迅速了解什么是集成学习
|
3月前
|
机器学习/深度学习 运维 算法
【阿里天池-医学影像报告异常检测】3 机器学习模型训练及集成学习Baseline开源
本文介绍了一个基于XGBoost、LightGBM和逻辑回归的集成学习模型,用于医学影像报告异常检测任务,并公开了达到0.83+准确率的基线代码。
59 9
|
3月前
|
人工智能
LLama+Mistral+…+Yi=? 免训练异构大模型集成学习框架DeePEn来了
【8月更文挑战第6天】DeePEn是一种免训练异构大模型集成学习框架,旨在通过融合多个不同架构和参数的大模型输出概率分布,提升整体性能。它首先将各模型输出映射至统一概率空间,然后进行聚合,并最终反转回单一模型空间以生成输出。实验证明,在知识问答和推理任务上,DeePEn相比单一大模型如LLaMA和Mistral有显著提升,但其效果受模型质量和数量影响,并且计算成本较高。[论文: https://arxiv.org/abs/2404.12715]
41 1
|
4月前
|
监控 druid Java
spring boot 集成配置阿里 Druid监控配置
spring boot 集成配置阿里 Druid监控配置
262 6
|
4月前
|
Java 关系型数据库 MySQL
如何实现Springboot+camunda+mysql的集成
【7月更文挑战第2天】集成Spring Boot、Camunda和MySQL的简要步骤: 1. 初始化Spring Boot项目,添加Camunda和MySQL驱动依赖。 2. 配置`application.properties`,包括数据库URL、用户名和密码。 3. 设置Camunda引擎属性,指定数据源。 4. 引入流程定义文件(如`.bpmn`)。 5. 创建服务处理流程操作,创建控制器接收请求。 6. Camunda自动在数据库创建表结构。 7. 启动应用,测试流程启动,如通过服务和控制器开始流程实例。 示例代码包括服务类启动流程实例及控制器接口。实际集成需按业务需求调整。
317 4
|
4月前
|
消息中间件 Java 测试技术
【RocketMQ系列八】SpringBoot集成RocketMQ-实现普通消息和事务消息
【RocketMQ系列八】SpringBoot集成RocketMQ-实现普通消息和事务消息
289 1