ABP文档 - EntityFramework 集成

文档目录html

 

本节内容:数据库

 

ABP可以使用任何ORM框架,它已经内置了EntityFrame(如下简称EF),这个文档将解释如何在ABP里使用EF,咱们假设你对EF已经有初步的了解。app

 

Nuget 包框架

在ABP里使用EF的Nuget包是Abp.EntityFramework,你应该把它加入到你的应用里,最好在你项目里单独创建一个EF程序集(dll),而后依赖该于这个包。ide

 

DbContextpost

如你所知,要使用EF,应当先为你的应用定义一个DbContext,以下所示:ui

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);
    }
}

除了从AbpDbContext继承(不是DbContext)外,其它的与普通的DbContext没分别,AbpDbContext有多个重载,你能够按须要使用它们。this

EF能够以一种约定的方式映射类到数据库表,你甚至不用进行配置,除非你自定义了一些东西,在这个例子里,咱们映射实体到不一样的表,按默认Task实体映射到Tasks表,但咱们把它修改为StsTasks表,也能够用数据注解特性代替配置。我更喜欢使用流畅的配置,你可按喜爱选择。spa

 

仓储code

仓储用来抽象来自更高层的数据访问,查看仓储文档获取更多。

 

默认仓储

Abp.EntityFramework为全部定义在你的DbContext里的实体,实现了默认的仓储,你不用建立仓储类,就能够直接使用预约义的仓储方法,例如:

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提供了一个基类EfRepositoryBase,能够很容易地实现仓储。为实现IRepository接口,你的仓储能够直接继承该类,但最好是扩展EfRepositoryBase类,你能够在你的仓储里添加共享/通用的方法。一个SimpleTaskSystem应用的全部仓储的基类示例:

//Base class for all repositories in my application
public class SimpleTaskSystemRepositoryBase<TEntity, TPrimaryKey> : EfRepositoryBase<SimpleTaskSystemDbContext, TEntity, TPrimaryKey>
    where TEntity : class, IEntity<TPrimaryKey>
{
    public SimpleTaskSystemRepositoryBase(IDbContextProvider<SimpleTaskSystemDbContext> dbContextProvider)
        : base(dbContextProvider)
    {
    }

    //add common methods for all repositories
}

//A shortcut for entities those have integer Id
public class SimpleTaskSystemRepositoryBase<TEntity> : SimpleTaskSystemRepositoryBase<TEntity, int>
    where TEntity : class, IEntity<int>
{
    public SimpleTaskSystemRepositoryBase(IDbContextProvider<SimpleTaskSystemDbContext> dbContextProvider)
        : base(dbContextProvider)
    {
    }

    //do not add any method here, add to the class above (because this class inherits it)

注意:咱们从 EfRepositoryBase<SimpleTaskSystemDbContext, TEntity, TPrimaryKey>继承,这代表在咱们仓储里,ABP使用SimpleTaskSystemDbContext 。

 

自定义仓储示例

为实现一个自定义仓储,能够直接继承你应用里特定的仓储基类(如咱们上面建立的)。

假设咱们有一个Task实体,它能够分配给一个Person(实体),而且一个Task有一个State(new,assigned,completed...),咱们须要编写一个自定义方法,经过一些条件和预先获取的AssisgnedPerson属性使用一条数据库查询,获取Tasks列表,示例代码以下:

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,而后实现它,GetAll()返回IQueryable<Task>,而后咱们使用给定的参数添加一些Where过滤,最后咱们能够调用ToList()来获取Tasks列表。

你能够在你的仓储方法里使用Context对象,从而直接使用EF的API。

注意:在领域/核心层定义自定义的仓储接口,在EF所在项目层里实现接口,所以你能够在任何项目里注入这个接口而不用引用EF。

 

仓储最佳实践

  • 尽量使用默认仓储,即便你有一个某实体的自定义的仓储,你也可使用默认仓储(当使用标准的仓储方法)。
  • 为你的应用里的自定义仓储建立一个仓储基类,如上面那样定义。
  • 在领域层定义你自定义仓储的接口(启动模板里的.Core项目),在EF所在项目里定义自定义仓储的类。

 

kid1412附:英文原文:http://www.aspnetboilerplate.com/Pages/Documents/EntityFramework-Integration 

相关文章
相关标签/搜索