本文翻译自ABP的官方教程《EntityFramework Integration》,地址为:http://aspnetboilerplate.com/Pages/Documents/EntityFramework-Integration

ABP 可以与任何 ORM 框架协同工作,它内置了对 EntityFramework 的集成支持。本文将介绍如何在 ABP 中使用 EntityFramework。本文假定你已经初步掌握了EntityFramework。

译者注:怎么才算初步掌握了 EntityFramework 呢?译者认为应当懂得使用 Code First 模式进行CRUD。

1 Nuget 包

要在 ABP 中使用 EntityFramework 作为 ORM 框架的话,需要到 Nuget 上下载一个名为 Abp.EntityFramework的包。比较好的做法是:新建一个独立的程序集 (dll),然后在这个程序集中调用这个包和 EntityFramework。

2 创建 DbContext(Creating DbContext)

要使用 EntityFramework,首先需要定义一个 DbContext 类。下面是一个DbContex 类的示例:

public class SimpleTaskSystemDbContext : AbpDbContext
{
public virtual IDbSet<Person> People { get; set; } public virtual IDbSet<Task> Tasks { get; set; }
public SimpleTaskSystemDbContext()
: base("MyConnectionStringName")
{ } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Person>().ToTable("StsPeople");
modelBuilder.Entity<Task>().ToTable("StsTasks").HasOptional(t=> t.AssignedPerson);
} }

上面的 SimpleTaskSystemDbContext 本质上是一个 DbContext 类,它派生自 AbpDbContext,而不是 DbContext。AbpDbContext 提供了很多重载的构造函数,如果需要的话,我们可以使用它。EntityFramework 可以使用约定的方式来映射实体和数据表。除非你想进行自定义映射,否则你甚至不需要做任何配置。在上例中,我们将实体映射到了不同的表中。默认情况下(按照约定优先于配置的原则,会默认采用约定的方式),Task 实体会映射到 Tasks 表,但在这里我们将它映射到了 StsTasks 表。相比起使用 Data Annotation 模式来进行自定义映射,我更喜欢使用 Fluent API 模式。当然,你可以选择你所喜欢的模式,这里没有特别的限制。

3 仓储(Repositories)

ABP 提供了一个名为 EfRepositoryBase 的基类,这使得实现仓储变得简单快捷。要实现 IRepository 接口,你只需要从这个基类进行派生即可。但是更好的做法是,自定义一个派生自 EfRepositoryBase 的基类,然后在这个基类中添加一些通用的方法。这样做的好处是,所有派生自这个基类的仓储都继承了这些通用方法。

(1)应用程序专用的仓储基类(Application specific base repository class)

在下面的例子中,我们定义了一个名为 SimpleTaskSystem 仓储基类,这个类是此应用程序所专用的。

// 应用程序中的所有仓储的基类
public class SimpleTaskSystemRepositoryBase<TEntity, TPrimaryKey> : EfRepositoryBase<SimpleTaskSystemDbContext, TEntity, TPrimaryKey>
    where TEntity : class, IEntity<TPrimaryKey>
{
  public SimpleTaskSystemRepositoryBase(IDbContextProvider<SimpleTaskSyst emDbContext> dbContextProvider)
: base(dbContextProvider)
{ }   //添加仓储基类的通用方法 } public class SimpleTaskSystemRepositoryBase<TEntity> : SimpleTaskSystemRepositoryBase<TEntity, int>
where TEntity : class, IEntity<int>
{
   public SimpleTaskSystemRepositoryBase(IDbContextProvider<SimpleTaskSyst emDbContext> dbContextProvider)
: base(dbContextProvider)
{ }   // 不 要 在 这 里 添 加 任 何 通 用 方 法 ,通 用 方 法 应 当 被添加到 上 面 的 基 类 中(MyRepositoryBase<TEntity, TPrimaryKey>) }

需 要 注 意 的 是 , 我 们 继 承 了 基 类EfRepositoryBase<SimpleTaskSystemDbContext, TEntity, TPrimaryKey>。这相当于做了一个声明,它会让 ABP 在仓储中调用 SimpleTaskSystemDbContext。

(2)仓储实现(Implementing a repository)

如果你只想使用预定义的仓储方法的话,你甚至不需要为实体创建仓储类。如下所示:

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>)对象,然后使用预定义的方法。查看仓储文档以获得预定义方法的列表。

(3)自定义仓储(Custom repositories)

要实现自定义仓储,只要从上面所创建的应用程序专用的仓储基类(SimpleTaskSystemRepositoryBase)派生即可。

假定我们有一个名为 Task 的实体,它可以被赋予 Person 实体。Task 有一个状态属性(值为新建、已分配、已完成等)。我们需要编写一个自定义方法,这个方法能根据某些条件获取 Task 列表,并且使得 Task 的 AssisgnedPerson 属性可以在一次数据库查询中被加载(使用 EntityFramework 的贪婪加载方法 Include)。如下所示:

public interface ITaskRepository : IRepository<Task,   long> 
{
List<Task> GetAllWithPeople(int? assignedPersonId, TaskState? state);
} public class TaskRepository : SimpleTaskSystemRepositoryBase<Task, long>, ITaskRepository
{
public TaskRepository(IDbContextProvider<SimpleTaskSystemDbContext> dbContextProvider)
: base(dbContextProvider)
{
}    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)
.Include(task => task.AssignedPerson)
.ToList();
}
}

我们首先定义了一个名为 ITaskRepository 的接口,紧接着定义了一个名为 TaskRepository 的类来实现它。预定义方法 GetAll()返回了一个 IQueryable<Task> 对象,接着我们将参数放入到 Where 筛选器中,最后调用 ToList()来获得一个 Task 列表。此外,我们可以通过调用 base.Context 属性来获得一个 DbContext 对象,这样一来,你就可以直接使用 Entity Framework 的所有功能。

仓储类应当在构造函数中获取IDbContextProvider对象。通过这种方式,在单元测试的时候,我们可以很容易地注入一个虚拟的 DbContext Provider 对象;而在运行的时候,ABP 会根据配置注入相应的 DbContext Provider 对象。

ABP 基础设施层——集成 Entity Framework的更多相关文章

  1. ABP 基础设施层——集成 NHibernate

    本文翻译自ABP的官方教程<NHibernate Integration>,地址为:http://aspnetboilerplate.com/Pages/Documents/NHibern ...

  2. 集成 Entity Framework

    ABP 基础设施层——集成 Entity Framework 本文翻译自ABP的官方教程<EntityFramework Integration>,地址为:http://aspnetboi ...

  3. UWP开发之ORM实践:如何使用Entity Framework Core做SQLite数据持久层?

    选择SQLite的理由 在做UWP开发的时候我们首选的本地数据库一般都是Sqlite,我以前也不知道为啥?后来仔细研究了一下也是有原因的: 1,微软做的UWP应用大部分也是用Sqlite.或者说是微软 ...

  4. Asp.Net MVC 模型(使用Entity Framework创建模型类) - Part.1

    这篇教程的目的是解释在创建ASP.NET MVC应用程序时,如何使用Microsoft Entity Framework来创建数据访问类.这篇教程假设你事先对Microsoft Entity Fram ...

  5. Asp.Net MVC 模型(使用Entity Framework创建模型类)

    这篇教程的目的是解释在创建ASP.NET MVC应用程序时,如何使用Microsoft Entity Framework来创建数据访问类.这篇教程假设你事先对Microsoft Entity Fram ...

  6. ABP框架系列之三:(Entity Framework Integration-实体框架集成)

    ASP.NET Boilerplate can work with any O/RM framework. It has built-in integration with EntityFramewo ...

  7. ABP 教程文档 1-1 手把手引进门之 ASP.NET Core & Entity Framework Core(官方教程翻译版 版本3.2.5)

    本文是ABP官方文档翻译版,翻译基于 3.2.5 版本 官方文档分四部分 一. 教程文档 二.ABP 框架 三.zero 模块 四.其他(中文翻译资源) 本篇是第一部分的第一篇. 第一部分分三篇 1- ...

  8. ABP官方文档翻译 9.2 Entity Framework Core

    Entity Framework Core 介绍 DbContext 配置 在Startup类中 在模块PreInitialize方法中 仓储 默认仓储 自定义仓储 应用程序特定基础仓储类 自定义仓储 ...

  9. ABP框架系列之二:(Entity Framework Core-实体核心框架)

    Introduction(介绍) Abp.EntityFrameworkCore nuget package is used to integrate to Entity Framework (EF) ...

随机推荐

  1. Subquery typo with using in(转)

    Subquery typo with using in Do you use the following syntax?   SELECT * FROM TABLE WHERE COLUMN IN ( ...

  2. 使用sizemask来确保索引不越界

    [使用sizemask来确保索引不越界] 在redis的字典实现中,有一个sizemask字段. 此字段的作用是当使用下标访问数据时,确保下标不越界. 如当前size为8时,sizemask为7(0x ...

  3. IE6、IE7、Firefox中margin问题及input解决办法

    margin不居中的问题 .div{ margin:10px;/*ff*/ *margin:15px;/*ie7*/ _margin:15px;/*ie6*/  尺寸会变为正常的两倍,按道理应为5px ...

  4. 批量删除进程清理 minerd

    发现顽固minerd 进程与ntp一起启动,所以一起杀掉 yum remove ntp kill -9 `ps -ef | grep ntp|awk '{print $2}'` kill -9 `ps ...

  5. TensorFlow—CNN—CIFAR数据集分类

  6. collections之deque【双向队列】与Queue【单向队列】

    今天来向大家介绍两个队列,一个是deque,双向队列,另外一个是Queue,单向队列,队列和堆栈不同,队列为先进先出,大家还需要注意一下,双向队列为collections模块中的类,而Queue为qu ...

  7. html菜单和课程表

    菜单: <html> <head> <meta charset="utf-8"> <title>菜单练习</title> ...

  8. 5. Import the project download from Git

    1.Recover eclipse project Copy .project from other project(You can new a project first in eclipse. T ...

  9. JVM 系列(一)类加载

    JVM 系列(一)类加载 类加载机制是指把 class 文件加载到内存,并对数据进行校验.解析和初始化,最终形成 JVM 可以直接使用的 Java 类型的过程. ClassLoader 加载一个 cl ...

  10. swift 设置string 中汉字中变色等处理代码

    我们在做弹窗 或者显示label string的时候经常会用到字体变色 变大 等特殊处理, swift中提供一个函数 NSMutableAttributedString 使用方法简介 var main ...