ABP理論學習之EntityFramework集成


返回總目錄


本篇目錄

ABP可以使用任何ORM框架工作,並且已經內置了EntityFramework集成。這篇文章會解釋如何在ABP中使用EntityFramework。閱讀本文的前提是假設你已經熟悉了EF的基本知識。

Nuget包###

在ABP中使用EF作為ORM的Nuget包是Abp.EntityFramework。你應該將它添加到應用程序中。最好在應用程序中分離的程序集(dll)中實現EntityFramework,並讓該程序集依賴Abp.EntityFramework包。

創建DbContext###

要使用EF工作,你應該為應用程序定義一個DbContext。定義DbContext的一個例子如下所示:

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的構造函數有很多重載。你可以使用你需要的那個。

EntityFramework可以以一種慣例的方式將類映射到數據庫中對應的表。除非你要做一些自定義的東西,否則你不需要做任何配置。在這個例子中,我們將實體映射到不同的表,默認地,Task實體會映射到Tasks表。但是我們將它改成了StsTasks表,這里沒有用數據注解特性配置,我更喜歡使用流暢的配置。你也可以選擇你喜歡的方式。

倉儲###

ABP提供了一個基類EfRepositoryBase可以輕松地實現倉儲。為了實習IRepository接口,只需要從這個類中派生倉儲就可以了。但是最好創建你自己的繼承了EfRepositoryBase的基類。這樣,你就可以給倉儲輕松地添加一些共享的方法了。

倉儲基類

一個簡單任務系統(SimpleTaskSystem)應用的所有倉儲的基類例子如下所示:

//所有倉儲的基類
public class SimpleTaskSystemRepositoryBase<TEntity, TPrimaryKey> : EfRepositoryBase<SimpleTaskSystemDbContext, TEntity, TPrimaryKey>
    where TEntity : class, IEntity<TPrimaryKey>
{
    public SimpleTaskSystemRepositoryBase(IDbContextProvider<SimpleTaskSystemDbContext> dbContextProvider)
        : base(dbContextProvider)
    {
    }

    //為所有的倉儲添加一些公共的方法
}

//Id為整數的實體的快捷方式
public class SimpleTaskSystemRepositoryBase<TEntity> : SimpleTaskSystemRepositoryBase<TEntity, int>
    where TEntity : class, IEntity<int>
{
    public SimpleTaskSystemRepositoryBase(IDbContextProvider<SimpleTaskSystemDbContext> dbContextProvider)
        : base(dbContextProvider)
    {
    }

    //不要在這里添加任何方法,在上面的方法中添加(因為該方法繼承了上面的方法)
}

注意我們是從EfRepositoryBase<SimpleTaskSystemDbContext, TEntity, TPrimaryKey>繼承的。這就聲明了ABP在倉儲中使用的數據上下文是SimpleTaskSystemDbContext。

默認實現倉儲

你不需要為實體類創建倉儲,只需要使用預定義的倉儲方法。例子:

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<TEntity,TPrimaryKey>),然后使用預定義的方法。所有預定義的方法列表,請查看倉儲文檔

自定義倉儲方法

要實現一個自定義的倉儲,只需要從上面創建的倉儲基類中派生就可以了。

假設我們有一個Task(任務)實體,該任務可以派給一個Person(人)實體,而且Task實體有這么幾種狀態,包括new,assigned,completed等等。我們可能需要寫一個自定義方法來根據一些條件和AssignedPerson來獲取任務的列表。看下面的代碼:

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 ,然后使用給定的參數添加了一些 Where過濾。最后使用 ToList()獲得Tasks的列表。

你也可以在倉儲方法中使用Context對象到達DbContext,然后可以直接使用EF基礎設施了。

倉儲應該獲得一個IDbContextProvider。這樣的話,我們就可以在單元測試中輕松地注入一個偽造的DbContext提供者了。在運行時,ABP會自動地注入正確的DbContext提供者。

閱讀其他###

你也可以查看倉儲文檔獲取更多關於倉儲的知識。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM