文檔目錄html
本節內容:數據庫
ABP可以使用任何ORM框架,它已經內置了EntityFrame(如下簡稱EF),這個文檔將解釋如何在ABP裏使用EF,咱們假設你對EF已經有初步的瞭解。app
在ABP裏使用EF的Nuget包是Abp.EntityFramework,你應該把它加入到你的應用裏,最好在你項目裏單獨創建一個EF程序集(dll),而後依賴該於這個包。ide
如你所知,要使用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
倉儲用來抽象來自更高層的數據訪問,查看倉儲文檔獲取更多。
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。
kid1412附:英文原文:http://www.aspnetboilerplate.com/Pages/Documents/EntityFramework-Integration