ABP框架系列之二:(Entity Framework Core-实体核心框架)
Introduction(介绍)
Abp.EntityFrameworkCore nuget package is used to integrate to Entity Framework (EF) Core ORM framework. After installing this package, we should also add a DependsOn attribute for AbpEntityFrameworkCoreModule.
abp.entityframeworkcore NuGet包是用来整合实体框架(EF)核心的ORM框架。安装此包后,我们还应该加上一个AbpEntityFrameworkCoreModule依赖属性。
DbContext
EF Core requires to define a class derived from DbContext. In ABP, we should derive from AbpDbContext as shown below:
EF核心需要定义来自DbContext类。在ABP,我们应该从abpdbcontext获得,如下所示:
public class MyDbContext : AbpDbContext
{
public DbSet<Product> Products { get; set; } public MyDbContext(DbContextOptions<MyDbContext> options)
: base(options)
{
}
}
Constructor should get a DbContextOptions<T> as shown above. Parameter name must be options. It's not possible to change it because ABP provides it as anonymous object parameter.
构造函数必须得到 DbContextOptions<T> 如上面所示. 参数名称必须是选项。无法改变它,因为ABP将它作为匿名对象参数提供。
Configuration(配置)
In Startup Class(启动类)
Use AddAbpDbContext method on service collection in ConfigureServices method as shown below:
services.AddAbpDbContext<MyDbContext>(options =>
{
options.DbContextOptions.UseSqlServer(options.ConnectionString);
});
For non web projects, we will not have a Startup class. In that case, we can use Configuration.Modules.AbpEfCore().AddDbContext method in our module class to configure DbContext, as shown below:
对于非Web项目,我们将不会有一个启动类。在这种情况下,我们可以使用配置模块。abpefcore().adddbcontext方法在我们的模块配置DbContext类,如下图所示:
Configuration.Modules.AbpEfCore().AddDbContext<MyDbContext>(options =>
{
options.DbContextOptions.UseSqlServer(options.ConnectionString);
});
We used given connection string and used Sql Server as database provider. options.ConnectionString is the default connection string (see next section) normally. But ABP uses IConnectionStringResolver to determine it. So, this behaviour can be changed and connection string can be determined dynamically. The action passed to AddDbContext is called whenever a DbContext instance will be created. So, you also have a chance to return different connection string conditionally.
我们使用给定的连接字符串,并使用SQL Server作为数据库提供程序。options.connectionstring是默认的连接字符串(见下一节)正常。但ABP采用iconnectionstringresolver去确定。因此,可以改变这种行为,并可以动态地确定连接字符串。行动通过adddbcontext时调用DbContext的实例将被创建。因此,您还可以有条件地返回不同的连接字符串。
So, where to set default connection string?
In Module PreInitialize
You can do it in PreInitialize of your module as shown below:
public class MyEfCoreAppModule : AbpModule
{
public override void PreInitialize()
{
Configuration.DefaultNameOrConnectionString = GetConnectionString("Default");
...
}
}
So, you can define GetConnectionString method simply returns the connection string from a configuration file (generally from appsettings.json).
所以,你可以定义getconnectionstring方法只返回一个配置文件中的连接字符串(一般从appSettings.JSON)。
Repositories(仓库)
Repositories are used to abstract data access from higher layers. See repository documentation for more.
存储库用于从高层抽象数据访问。更多信息请参见库文档。
Default Repositories(默认的仓库)
Abp.EntityFrameworkCore implements default repositories for all entities defined in your DbContext. You don't have to create repository classes to use predefined repository methods.
abp.entityframeworkcore实现在你定义的所有实体的默认库DbContext。您不必创建存储库类以使用预定义的存储库方法。Example:
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 contructor-injects IRepository<Person> and uses the Insert method. In this way, you can easily inject IRepository<TEntity> (or IRepository<TEntity, TPrimaryKey>) and use predefined methods.
personappservice构造函数注入IRepository <person>采用插入方法。这样,你可以很容易地注入IRepository < tentity >(或< tentity IRepository,tprimarykey >),使用预定义的方法。
Custom Repositories(自定义的仓库)
If standard repository methods are not sufficient, you can create custom repository classes for your entities.
如果标准存储库方法还不够,您可以为实体创建自定义存储库类。
Application Specific Base Repository Class
ASP.NET Boilerplate provides a base class EfCoreRepositoryBase to implement repositories easily. To implement IRepository interface, you can just derive your repository from this class. But it's better to create your own base class that extens EfRepositoryBase. Thus, you can add shared/common methods to your repositories easily. An example base class all for repositories of a SimpleTaskSystem application:
ASP.NET boilerplate 提供了基本的类efcorerepositorybase 库很容易实现。实现irepository接口,你可以获得这个类的任何库。但它是更好的创建你自己的类,扩展efrepositorybase。因此,你可以添加到你的库共享/普通的方法很容易。在所有的库类的例子:一个simpletasksystem应用
//Base class for all repositories in my application
public class SimpleTaskSystemRepositoryBase<TEntity, TPrimaryKey> : EfCoreRepositoryBase<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)
}
Notice that we're inheriting from EfCoreRepositoryBase<SimpleTaskSystemDbContext, TEntity, TPrimaryKey>. This declares to ASP.NET Boilerplate to use SimpleTaskSystemDbContext in our repositories.
注意,我们从efcorerepositorybase < simpletasksystemdbcontext,TEntity,tprimarykey >继承。这表明ASP.NET Boilerplate 在我们的库中使用simpletasksystemdbcontext。
By default, all repositories for your given DbContext (SimpleTaskSystemDbContext in this example) is implemented using EfCoreRepositoryBase. You can replace it to your own repository base repository class by addingAutoRepositoryTypes attribute to your DbContext as shown below:
默认情况下,你指定的DbContext所有仓库(simpletasksystemdbcontext这个例子)是用efcorerepositorybase。你可以换到你自己的库库的类中添加属性到你autorepositorytypes DbContext如下所示:
[AutoRepositoryTypes(
typeof(IRepository<>),
typeof(IRepository<,>),
typeof(SimpleTaskSystemEfRepositoryBase<>),
typeof(SimpleTaskSystemEfRepositoryBase<,>)
)]
public class SimpleTaskSystemDbContext : AbpDbContext
{
...
}
Custom Repository Example
To implement a custom repository, just derive from your application specific base repository class we created above.
Assume that we have a Task entity that can be assigned to a Person (entity) and a Task has a State (new, assigned, completed... and so on). We may need to write a custom method to get list of Tasks with some conditions and with AssisgnedPerson property pre-fetched (included) in a single database query. See the example code:
要实现自定义存储库,只需从上面创建的应用程序特定的基础存储库类中获得。
假设我们有一个任务实体可以分配给person(实体),任务有一个状态(新的,分配的,完成的)…等等)。我们需要写一个获得有条件的任务列表的自定义方法和属性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();
}
}
We first defined ITaskRepository and then implemented it. GetAll() returns IQueryable<Task>, then we can add some Where filters using given parameters. Finally we can call ToList() to get list of Tasks.
我们首先定义itaskrepository然后实现它。getall()返回IQueryable <task>,然后我们可以添加一些过滤器使用给定的参数。最后,我们可以称tolist()得到任务列表。
You can also use Context object in repository methods to reach to your DbContext and directly use Entity Framework APIs.
Note: Define the custom repository interface in the domain/core layer, implement it in the EntityFrameworkCore project for layered applications. Thus, you can inject the interface from any project without referencing to EF Core.
你也可以在库的方法使用上下文对象到你的DbContext和直接使用实体框架的API。
注:定义域/核心层的自定义库的接口,实现其在EntityFrameworkCore的项目分层中的应用。因此,您可以在不引用EF内核的情况下从任何项目注入接口。
Replacing Default Repositories
Even you have created a TaskRepository as shown above, any class can still inject IRepository<Task, long> and use it. That's not a problem in most cases. But, what if you overrided a base method in your custom repository? Say that you have overrided Delete method in your custom repository to add a custom behaviour on delete. If a class injects IRepository<Task, long> and use the default repository to Delete a task, your custom behaviour will not work. To overcome this issue, you can replace your custom repository implementation with the default one like shown below:
即使你已经创建了一个taskrepository如上所示,任何类仍然可以注入IRepository <task,long>,并使用它。在大多数情况下这都不是问题。但是,如果你在你的自定义库基础之上的方法吗?说你已经超过了删除自定义库的方法添加一个自定义的行为上删除。如果一个类注入IRepository <task,long>,并使用默认的存储库中删除任务,自定义的行为将不工作。为了克服这个问题,您可以用如下所示的默认选项替换您的自定义存储库实现:
Configuration.ReplaceService<IRepository<Task, Guid>>(() =>
{
IocManager.IocContainer.Register(
Component.For<IRepository<Task, Guid>, ITaskRepository, TaskRepository>()
.ImplementedBy<TaskRepository>()
.LifestyleTransient()
);
});
We registered TaskRepository for IRepository<Task, Guid>, ITaskRepository and TaskRepository. So, any one of these can be injected to use the TaskRepository.
Repository Best Practices(仓库的最佳实践)
- Use default repositories wherever it's possible. You can use default repository even you have a custom repository for an entity (if you will use standard repository methods).
- Always create repository base class for your application for custom repositories, as defined above.
- Define interfaces for your custom repositories in domain layer (.Core project in startup template), custom repository classes in .EntityFrameworkCore project if you want to abstract EF Core from your domain/application.
在可能的地方使用默认存储库。您可以使用默认存储库,即使您有实体的自定义存储库(如果您使用标准存储库方法)。
始终为您的自定义存储库应用程序创建存储库基类,如上所述。
定义自定义库在领域层的接口(在启动模板核心项目),自定义库类的。如果你想从你的摘要EF核心域/应用项目entityframeworkcore。
ABP框架系列之二:(Entity Framework Core-实体核心框架)的更多相关文章
- ABP官方文档翻译 9.2 Entity Framework Core
Entity Framework Core 介绍 DbContext 配置 在Startup类中 在模块PreInitialize方法中 仓储 默认仓储 自定义仓储 应用程序特定基础仓储类 自定义仓储 ...
- ABP框架系列之三:(Entity Framework Integration-实体框架集成)
ASP.NET Boilerplate can work with any O/RM framework. It has built-in integration with EntityFramewo ...
- .net core Entity Framework Core Code First 框架 分层开发
由于之前苦于无法把 Entityframework 跟Web层剥离.找了很久..找到了这个框架..分享给大家.. GitHub 地址:https://github.com/chsakell/dotn ...
- ABP 教程文档 1-1 手把手引进门之 ASP.NET Core & Entity Framework Core(官方教程翻译版 版本3.2.5)
本文是ABP官方文档翻译版,翻译基于 3.2.5 版本 官方文档分四部分 一. 教程文档 二.ABP 框架 三.zero 模块 四.其他(中文翻译资源) 本篇是第一部分的第一篇. 第一部分分三篇 1- ...
- NET Core & Entity Framework Core
ABP 教程文档 1-1 手把手引进门之 ASP.NET Core & Entity Framework Core(官方教程翻译版 版本3.2.5) 本文是ABP官方文档翻译版,翻译基于 ...
- Entity Framework Core 1.1 Preview 1 简介
实体框架核心(EF Core)是Entity Framework的一个轻量级,可扩展和跨平台版本. 10月25日,Entity Framework Core 1.1 Preview 1发布了. 升级到 ...
- [Abp 源码分析]七、仓储与 Entity Framework Core
0.简介 Abp 框架在其内部实现了仓储模式,并且支持 EF Core 与 Dapper 来进行数据库连接与管理,你可以很方便地通过注入通用仓储来操作你的数据,而不需要你自己来为每一个实体定义单独的仓 ...
- Entity Framework Core系列之DbContext(删除)
上一篇我们介绍了Entity Framework Core系列之DbContext(修改),这一篇我们介绍下删除数据 修改实体的方法取决于context是否正在跟踪需要删除的实体. 下面的示例中con ...
- Entity Framework Core系列之DbContext(修改)
上一篇我们介绍了Entity Framework Core系列之DbContext(添加),这一篇我们介绍下修改数据 修改实体的方法取决于context是否正在跟踪需要修改的实体. 下面的示例中实体由 ...
随机推荐
- 1、ZooKeeper 基本概念、使用方法、实践场景
ZooKeeper 基本概念 ZooKeeper 是面向分布式应用的协调服务,其实现了树形结构的数据模型(与文件系统类似),并且提供了简洁的编程原语.ZooKeeper 能够作为基础,用于构建更高层级 ...
- 1、Shiro 安全框架与Spring 整合详解
Apache Shiro 是一个安全认证框架,和 Spring Security 相比,在于他使用了比较简洁易懂的认证和授权方式.其提供的 native-session(即把用户认证后的授权信息保存在 ...
- 1、根"/"目录结构
1.目录结构 FSH [root@localhost /]# tree -L . ├── bin -> usr/bin #普通用户使用的命令 ├── boot #存放系统启动相关文件,例如ker ...
- redis持久化 (rdb
RDB(快照持久化) RDB(redis database),可以理解为快照/内存快照,RDB持久化过程是将当前进程中的数据生成快照存储到硬盘中 触发机制RDB持久化的触发机制分为两种,手动触发和自动 ...
- ORACLE重装之后恢复数据库,相当于sqlserver的附加数据库
在开发机器上经常会遇到重装系统的问题,重装之前如果ORACLE没有及时备份的话重装之后就纠结了,数据还原很头疼. 各种娘中只能找到一些ORACLE安装与重装系统前目录相同的解决办法,目录不同就没招了. ...
- Shell脚本1-20例
1.每天生成一个文件 描述:请按照这样的日期格式(xxxx-xx-xx)每日生成一个文件,例如今天生成的文件为)2017-07-05.log, 并且把磁盘的使用情况写到到这个文件中,(不用考虑cron ...
- python入门学习2
变量 变量名就像我们现实社会的名字,把一个值赋值给一个名字时,它会存储在存储中,称之为变量(Variable),在大多数语言中,都把这种行为称为“给变量赋值”或“把值存储在变量中”. 而Python与 ...
- jquery中的 deferred之 deferred对象 (一)
案例: var def=$.Deferred(); console.log(def);//答案见 图1 图1: deferred就是一个有这些方法的对象. 看源码分析: Deferred: funct ...
- VideoView 监听视频格式不支持时的错误。
视频播放格式不支持的处理https://www.cnblogs.com/ygj0930/p/7737209.html 不处理的情况下,默认会有弹框提示:不支持该视频格式. mVideoView.set ...
- Lua中面向对象
一.Lua中类的简单实现: (1)版本——摘自 Cocos2.0中的: --Create an class. function class(classname, super) local superT ...