EntityFramework 集成

ASP.NET Boilerplate可以与任何O / RM框架一起使用。它与EntityFramework内置集成。本文档将解释如何将EntityFramework与ASP.NET Boilerplate一起使用。假设您已经熟悉基本级别的EntityFramework。

NuGet包

在ASP.NET Boilerplate中使用EntityFramework作为O / RM的NuGet包是  Abp.EntityFramework您应该将它添加到您的应用程序中。最好在应用程序中的单独程序集(dll)中实现EntityFramework,并依赖于此程序集中的该程序包。

DbContext

如您所知,要使用EntityFramework,您应该为您的应用程序定义一个DbContext类。DbContext示例如下所示:

public class SimpleTaskSystemDbContext : AbpDbContext
{
    public virtual IDbSet<Person> People { get; set; }
    public virtual IDbSet<Task> Tasks { get; set; }

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

    }
    
    public SimpleTaskSystemDbContext(string nameOrConnectionString)
        : base(nameOrConnectionString)
    {

    }

    public SimpleTaskSystemDbContext(DbConnection existingConnection)
        : base(existingConnection, false)
    {

    }

    public SimpleTaskSystemDbContext(DbConnection existingConnection, bool contextOwnsConnection)
        : base(existingConnection, contextOwnsConnection)
    {

    }

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

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

它是一个常规的DbContext类,除了以下规则:

EntityFramework可以以传统方式将类映射到数据库表。除非你做一些自定义的东西,否则你甚至不需要进行配置。在此示例中,我们将实体映射到不同的表。默认情况下,Task实体映射到Tasks表。我们将它改为StsTasks表。不建议使用数据注释属性进行配置,建议您使用流畅配置。你可以选择你喜欢的。

存储库用于从较高层抽象数据访问。有关 详细信息,请参阅  存储库文档。 

默认存储库

该  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>)并使用预定义的方法。

自定义存储库

如果标准存储库方法不足,则可以为实体创建自定义存储库类。

特定于应用程序的库存储库类

ASP.NET Boilerplate提供了一个基类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 methods here, add them to the class above (because this class inherits it)
}

请注意,我们继承自EfRepositoryBase <SimpleTaskSystemDbContext,TEntity和TPrimaryKey>?这将ASP.NET Boilerplate设置为在我们的存储库中使用SimpleTaskSystemDbContext。

默认情况下,使用EfRepositoryBase实现给定DbContext(本示例中为SimpleTaskSystemDbContext)的所有存储库。您可以通过将AutoRepositoryTypes属性添加到DbContext来将其替换为您自己的基本存储库类,如下所示:

[AutoRepositoryTypes(
    typeof(IRepository<>),
    typeof(IRepository<,>),
    typeof(SimpleTaskSystemEfRepositoryBase<>),
    typeof(SimpleTaskSystemEfRepositoryBase<,>)
)]
public class SimpleTaskSystemDbContext : AbpDbContext
{
    ...
}
自定义存储库示例

要实现自定义存储库,只需从特定于应用程序的基本存储库类派生它,就像我们在上面创建的那样。

假设我们有一个可以分配给Person(实体)和任务状态的Task实体(new,assign,completed ......等等)。我们可能需要编写一个自定义方法来获取任务列表,包含一些条件,以及预先获取(包含)的AssisgnedPerson属性; 全部在一个数据库查询中。请参阅示例代码:

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()来获取任务列表。

您还可以使用存储库方法中的Context对象来访问DbContext,以便您可以直接使用Entity Framework API。 

注意:在域/核心层中定义自定义存储库接口,在EntityFrameworkproject中为分层应用程序实现它。这样,您可以从任何项目中注入接口,而无需实际引用EF。

存储库最佳实践

交易管理

ASP.NET Boilerplate具有内置  的工作单元,  用于管理数据库连接和事务。实体框架具有不同的  事务管理方法ASP.NET Boilerplate默认使用环境TransactionScope方法,但它还具有DbContext事务API的内置实现。如果要切换到DbContext事务API,可以在模块的PreInitialize方法中对其进行配置,   如下所示:

Configuration.ReplaceService<IEfTransactionStrategy, DbContextEfTransactionStrategy>(DependencyLifeStyle.Transient);

请记住将“ 使用Abp.Configuration.Startup; ” 添加到您的代码文件中,以便能够使用ReplaceService通用扩展方法。

此外,您的DbContext应该具有本文档的DbContext部分中描述的构造函数。

由于ASP.NET Boilerplate具有与EntityFramework的内置集成,因此它可以与EntityFramework支持的数据存储一起使用。我们的免费启动模板旨在与Sql Server一起使用,但您可以修改它们以使用不同的数据存储。

例如,如果您想使用MySql,请参阅  此文档

nidie.com.cn - 用心与你沟通