热线(9:00-18:00):13544706711
当前位置: 首页 > 教程技巧 > 

<<ABP文档>> EntityFramework 集成

时间: 2016/11/05 21:06:19

文档目录


 


本节内容:





 


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


 


Nuget 包


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


 


DbContext


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



public class SimpleTaskSystemDbContext : AbpDbContext
{
public virtual IDbSet People { get; set; }
public virtual IDbSet Tasks { get; set; }

public SimpleTaskSystemDbContext()
:
base("MyConnectionStringName")
{

}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.Entity
().ToTable("StsPeople");
modelBuilder.Entity
().ToTable("StsTasks").HasOptional(t => t.AssignedPerson);
}
}


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


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


 


仓储


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


 


默认仓储


Abp.EntityFramework为所有定义在你的DbContext里的实体,实现了默认的仓储,你不用创建仓储类,就可以直接使用预定义的仓储方法,例如:



public class PersonAppService : IPersonAppService
{
private readonly IRepository _personRepository;

public PersonAppService(IRepository 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),然后使用预定义方法,查看仓储文档了解所有预定义方法。


 


自定义仓储


如果标准的仓储方法不能满足,你可以为你的实体创建自定义的仓储类。


 


特定的仓储基类


ABP提供了一个基类EfRepositoryBase,可以很容易地实现仓储。为实现IRepository接口,你的仓储可以直接继承该类,但最好是扩展EfRepositoryBase类,你可以在你的仓储里添加共享/通用的方法。一个SimpleTaskSystem应用的所有仓储的基类示例:



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

//add common methods for all repositories
}

//A shortcut for entities those have integer Id
public class SimpleTaskSystemRepositoryBase : SimpleTaskSystemRepositoryBaseint>
where TEntity : class, IEntity<int>
{
public SimpleTaskSystemRepositoryBase(IDbContextProvider 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 : IRepositorylong>
{
List
GetAllWithPeople(int? assignedPersonId, TaskState? state);
}

public class TaskRepository : SimpleTaskSystemRepositoryBaselong>, ITaskRepository
{
public TaskRepository(IDbContextProvider dbContextProvider)
:
base(dbContextProvider)
{
}

public List 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对象,从而直接使用EF的API。


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


 


仓储最佳实践



  • 尽可能使用默认仓储,即使你有一个某实体的自定义的仓储,你也可以使用默认仓储(当使用标准的仓储方法)。

  • 为你的应用里的自定义仓储创建一个仓储基类,如上面那样定义。

  • 在领域层定义你自定义仓储的接口(启动模板里的.Core项目),在EF所在项目里定义自定义仓储的类。


 


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