本篇目录
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继承的。这就声明了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),然后使用预定义的方法。所有预定义的方法列表,请查看仓储文档。,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提供者。
本文转自tkbSimplest博客园博客,原文链接:http://www.cnblogs.com/farb/p/ABPEntityFramework.html,如需转载请自行联系原作者