ABP官方文档翻译 9.1 EntityFramework集成

EntityFramework集成

  • Nuget包
  • DbContext
  • 仓储
    • 默认仓储
    • 自定义仓储
      • 应用特定的基础仓储类
      • 自定义仓储示例
    • 仓储最佳实践
  • 事务管理
  • 数据存储

  ABP可以使用ORM框架,它内置集成EntityFramework。本文档将讲解ABP如何使用EntityFramework。假定你对EntityFramework已经有了初级水平。

Nuget包

  在ABP中使用Abp.EntityFramework nuget包扩展了EntityFramework。需要将它添加到工程中。最好在一个单独的程序集(dll)中实现EntityFramework并在此程序集中引用Abp.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类,除此之外它遵循以下规则:

  • AbpDbContext集成而不是DbContext。
  • 需要有构造函数如上面的示例(构造函数参数命名也需要一样)。说明:
    • 默认构造函数传递“Default”到基类作为连接字符串。所以,在web.config/app.config文件中有一个名为“Default”的连接字符串。ABP不使用个这构造函数,但是EF命令行迁移工具和工具命令(如 update-database)使用它。
    • nameOrConnectiongString参数的构造函数,ABP用来在运行时传递连接名称或字符串。
    • existingConnection参数的构造函数用于单元测试,ABP不直接使用。
    • existingConnectioncontxtOwnsConnection的构造函数,当使用DbContextEfTransactionStrategy时(参见下面的事务管理部分),ABP用于单数据库多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>)并使用预定义方法。

自定义仓储

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

应用特定的基础仓储类

  ABP提供了一个基础类EfRepositoryBase来实现仓储。为了实现IRepository接口,可以将你的仓储类从这个类集成。但是最好创建自己的基类并扩展EfRepositoryBase。从而,你可以在自己的仓储中添加shared/common方法或重写已经存在的方法。下面是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。

  默认,对于所有给定DbContext(在这个例子中为SimpleTaskDbContext)的仓储都使用EfRepositoryBase实现。你可以在你的DbContext中添加AutoRepository特性来使用自己的仓储基类,如下:

[AutoRepositoryTypes(
    typeof(IRepository<>),
    typeof(IRepository<,>),
    typeof(SimpleTaskSystemEfRepositoryBase<>),
    typeof(SimpleTaskSystemEfRepositoryBase<,>)
)]
public class SimpleTaskSystemDbContext : AbpDbContext
{
    ...
}

自定义仓储示例

  为了实现自定义仓储,在你的应用中继承一个以上我们定义的基础仓储类。

  假定,我们有一个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();
    }
}

  我们首先定义了ITaskRepostory接口并实现了它。GetAll()返回IQueryable<Task>,然后我们可以使用给定的参数添加一些Where过滤器。最后我们调用ToList()来获取Tasks列表。

  你也可以在仓储方法中使用Context对象引用你自己的DbContext,然后直接使用Entity Framework APIs。

  注意:对于分层应用,在domain/core层定义自定义仓储接口,在EntityFramework工程中实现它们。从而,你可以在任何工程中注入这个接口而不用引用EF。

仓储最佳实践

  • 在可能的地方使用默认仓储。即使你有一个实体的自定义仓储(如果你将使用标准的仓储方法),也可以使用默认的仓储。
  • 总是为自定义仓储创建仓储基类,如上面定义的那样。
  • 领域层定义自定义仓储的接口,如果你想将EF从你的domain/application中抽象出来,在EntityFramework工程中自定义仓储类。

事务管理

  ABP有内置的工作单元系统来管理数据库连接和事务。Entity Framework有不同的事务管理方式。ABP默认使用TransactionScope方式,但是也有DbContext事务API的内置实现。如果你想切换到DbContext事务API,可以在模块的PreInitialize方法中配置它:

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

  记住,在代码中添加"using Abp.Configuration.Startup"以便能使用ReplaceService的泛型扩展方法。

  另外,如在DbContext部分所描述的那样,你的DbContext需要有构造函数。

数据存储

  因为ABP内置集成EntityFramework,那么它就可以使用EntityFramework所支持的数据存储。我们免费的启动模板设计为使用Sql Server,但是你可以修改他们以便使用不同的数据存储。

  例如,如果你想使用MySql,请参见这个文档

返回主目录

时间: 2024-08-06 11:41:04

ABP官方文档翻译 9.1 EntityFramework集成的相关文章

ABP官方文档翻译 7.2 Hangfire集成

Hangfire集成 介绍 ASP.NET Core集成 ASP.NET MVC 5.x集成 面板授权 介绍 Hangfire是一个综合的后台job管理器.你可以 把它集成到ABP,用来取代默认的后台job管理器.Hangfire可以使用相同的后台jobAPI.因此,你的代码与Hangfire是独立的.但是,如果你喜欢的话,可以直接使用Hangfire的API. Hangfire集成依赖于使用的框架. ASP.NET Core集成 Abp.HangFire.AspNetCore包用来集成到ASP

ABP官方文档翻译 9.3 NHibernate集成

NHibernate集成 Nuget包 配置 实体映射 仓储 默认实现 自定义仓储 应用程序特定基础仓储类 ABP可以使用任何ORM框架,它内置集成NHibernate.此文档将讲解ABP如何使用NHibernate,假定你对NHibernate已经有了一定的了解. Nuget包 在ABP中实现NHibernate做为ORM框架的Nuget包为Abp.NHibernate.你需要在应用程序中添加它.最好在一个单独的程序集中实现NHibernate并在这个程序集里依赖Abp.NHibernate包

ABP官方文档翻译 7.3 Quartz集成

Quartz集成 介绍 安装 创建Jobs 计划安排Jobs 更多 介绍 Quartz是一个全功能的.开源的job计划安排系统,可以用在小的apps也可以用于大型的企业系统.Abp.Quartz包简化了ABP集成Quartz. ABP有內建的持久化后台job队列和后台worker系统.如果对于后台workers你有更高级的计划安排需求,Quartz会是一个更好的选择.对于持久化后台job队列,Hangfire也是一个好的选择. 安装 在工程中安装Abp.Quartz nuget包并在模块上为Ab

ABP官方文档翻译 5.4 SwaggerUI集成

SwaggerUI集成 介绍 ASP.NET Core 安装Nuget包 配置 测试 ASP.NET 5.x 安装Nuget包 配置 测试 介绍 在它的网站上:“...使用Swagger可用的API,你将获得可交互的文档.客户端SDK生成和可发现的能力”. ASP.NET Core 安装Nuget包 在你的网站上安装Swashbuckle 6.x nuget包. 配置 在Startup.cs的ConfigureServices方法中添加Swagger的配置代码: public IServiceP

ABP官方文档翻译 10.1 ABP Nuget包

ABP Nuget包 Packages Abp Abp.AspNetCore Abp.Web.Common Abp.Web Abp.Web.Mvc Abp.Web.Api Abp.Web.Api.OData Abp.Web.Resources Abp.Web.SignalR Abp.Owin Abp.EntityFramework.Common Abp.EntityFramework Abp.EntityFramework.GraphDiff Abp.EntityFrameworkCore Ab

ABP官方文档翻译 6.2.1 ASP.NET Core集成

ASP.NET Core 介绍 迁移到ASP.NET Core? 启动模板 配置 启动类 模块配置 控制器 应用服务作为控制器 过滤器 授权过滤器 审计Action过滤器 校验过滤器 工作单元Action过滤器 异常过滤器 结果过滤器 Ajax请求的结果缓存 模型绑定器 视图 客户端代理 集成测试 介绍 本文档描述了ABP如何集成ASP.NET Core.ASP.NET Core通过Abp.AspNetCore nuget包实现集成. 迁移到ASP.NET Core? 如果你已经有一个工程并考虑

ABP官方文档翻译 3.8 数据过滤器

数据顾虑器 介绍 预定义过滤器 ISoftDelete 何时使用? IMustHaveTenant 何时使用? IMayHaveTenant 何时使用 禁用过滤器 关于using语句 关于多租户 全局禁用过滤器 启用过滤器 设置过滤器参数 SetTenantId方法 ORM集成 Entity Framework EntityFramework.DynaamicFilters文档 其他ORMs 介绍 软删除模式是常用的模式,这种模式并没有从数据库中删除实体而是打上'deleted'的标记.所以,如

ABP官方文档翻译 6.1.2 MVC视图

ASP.NET MVC 视图 介绍 AbpWebViewPage基类 介绍 ABP通过Abp.Web.Mvc nuget包集成到MVC视图.你可以如往常一样创建正常的MVC视图. AbpWebViewPage基类 ABP提供了AbpWebViewPage,它定义了一些有用的属性和方法.如果你使用启动模板创建的工程,那么你所有的views都自动从这个基类继承. AbpWebViewPage定义了L方法用于本地化,IsGranted方法用于授权,IsFeatureEnabled和GetFeature

ABP官方文档翻译 3.3 仓储

 仓储 默认仓储 自定义仓储 自定义仓储接口 自定义仓储实现 基础仓储方法管理数据库连接 查询 获取单个实体 获取实体列表 关于IQueryable 自定义返回值 插入 更新 删除 其他 关于异步方法 管理数据库连接 仓储生命周期 仓储最佳实践 协调领域和数据映射层,使用类集合接口访问领域对象."(Martin Fowler) 实际上,仓储用来执行领域对象的数据库操作(实体和值类型).通常,每个对象(或聚合根)使用单独的仓储. 默认仓储 在ABP中,仓储类实现IRepository<TEn