ABP官方文档翻译 9.2 Entity Framework Core
Entity Framework Core
- 介绍
- DbContext
- 配置
- 在Startup类中
- 在模块PreInitialize方法中
- 仓储
- 默认仓储
- 自定义仓储
- 应用程序特定基础仓储类
- 自定义仓储示例
- 取代默认仓储
- 仓储最佳实践
介绍
Abp.EntityFrameworkCore nuget包用来集成EntityFramework(EF)Core ORM框架。安装这个包之后,我们需要为AbpEntityFrameworkCoreModule添加DependsOn特性。
DbContext
EF Core需要定义一个从DbContext继承的类。在ABP中,我们应该从AbpDbContext继承,如下所示:
public class MyDbContext : AbpDbContext {public DbSet<Product> Products { get; set; }public MyDbContext(DbContextOptions<MyDbContext> options): base(options){} }
如上所示,构造函数有一个DbContextOptions<T>的参数。
配置
在Startup类中
在ConfigureServices方法中使用AddAbpDbContext方法,如下所示:
services.AddAbpDbContext<MyDbContext>(options => {options.DbContextOptions.UseSqlServer(options.ConnectionString); });
对于非web工程,没有Startup类。在这种情况下,我们在模块中使用Configuration.Modules.AbpEfCore().AddDbContext方法来配置DbContext,如下所示:
Configuration.Modules.AbpEfCore().AddDbContext<MyDbContext>(options => {options.DbContextOptions.UseSqlServer(options.ConnectionString); });
我们使用给定的连接字符串并使用Sql Server作为数据库提供者。options.ConnectionString通常为默认的连接字符串(参见下一部分)。但是ABP使用IConnectionStringResolver来决定。所以,这种行为是可以改变的,连接字符串也可以动态决定。无论何时DbContext示例创建时,传递给AddDbContext的action都会执行。所以,你有机会可以根据条件返回不同的连接字符串。
所以,在什么地方设置默认字符串呢?
在模块PreInitialize方法中
你可以在模块的PreInitialize方法中设置默认字符串,如下所示:
public class MyEfCoreAppModule : AbpModule {public override void PreInitialize(){Configuration.DefaultNameOrConnectionString = GetConnectionString("Default");...} }
这样,你可以定义GetConnectionString方法从一个配置文件中(一般从appsettings.json文件)返回连接字符串。
仓储
仓储用来从高层抽象数据访问。参见仓储文档了解更多。
默认仓储
Abp.EntityFrameworkCore为所有定义在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提供了一个基类EfCoreRepositoryBase来简单的实现仓储。为了实现IRepository接口,你可以从这个类继承。但是最好创建自己的基础类并扩展EfRepositoryBase。这样,你可以容易的在自己的仓储中添加shared/common方法。下面为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) }
注意,我们从EfCoreRepositoryBase<SimpleTaskSystemDbContext,TEntity,TPrimaryKey>继承。这表明在我们的仓储中ABP使用SimpleTaskSystemDbContext。
默认,给定DbContext(在这个例子中为SimpleTaskSystemDbContext)的所有仓储使用EfCoreRepositoryBase实现。你可以通过在DbContext上添加AutoRepositoryTypes特性来使用自己的仓储基类来取代默认的仓储基类。如下所示:
[AutoRepositoryTypes(typeof(IRepository<>),typeof(IRepository<,>),typeof(SimpleTaskSystemEfRepositoryBase<>),typeof(SimpleTaskSystemEfRepositoryBase<,>) )] public class SimpleTaskSystemDbContext : AbpDbContext {... }
自定义仓储示例
为了实现自定义仓储,需要继承我们上面定义的特定仓储基础类。
假定,我们有一个Task实体,它可以被分配给一个Person(实体)并且任务有一个状态(new,assigned,completed...等等)。我们需要编写一个自定义方法基于一些条件并基于AssisgnedPerson属性预获取person实体,在一个数据库查询语句中来获取任务列表。参见示例代码:
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()方法来获取Tasks列表。
你也可以在仓储方法中使用Context对象引用你的DbContext并直接使用Entity Framework APIs。
注意:对于分层应用,在domain/core层定义自定义仓储接口,在EntityFrameworkCore工程中实现它。这样,你可以从任何工程中注入这个接口而不用引用EFCore。
取代默认仓储
即使你有一个TaskRepository,如上所示,任何类仍然可以注入IRepository<Task,long>并使用它。大多数情况下这没有什么问题。但是,如果在你的自定义仓储中重写了一个基类方法会怎样呢?比如说在你的自定义仓储中重写了Delete方法在删除时添加一个自定义行为。如果一个类注入IRepository<Task,long>并使用默认仓储删除一个任务,你自定义的行为将不会起作用。为了克服这个问题,你可以使用默认的你喜欢的一个取代你的自定义实现,如下所示:
Configuration.ReplaceService<IRepository<Task, Guid>>(() => {IocManager.IocContainer.Register(Component.For<IRepository<Task, Guid>, ITaskRepository, TaskRepository>().ImplementedBy<TaskRepository>().LifestyleTransient()); });
我们为IRepository<Task,Guid>,ITaskRepository和TaskRepository注册TaskRepository。所以,这些中的任何一个都可以被注入并使用TaskRepository。
仓储最佳实践
- 在任何可能的地方使用默认仓储。即使你已经有一个实体的默认仓储(如果你将使用标准仓储方法)也可以使用默认的仓储。
- 总是在应用程序中为自定义仓储创建仓储基类,如上定义。
- 如果你想从domain/application中抽象出EF Core,那么在domain层定义自定义仓储的接口(在启动模板中为.Core工程),在.EntityFrameworkCore工程中定义自定义仓储类。
返回主目录
转载于:https://www.cnblogs.com/xajh/p/7153017.html
ABP官方文档翻译 9.2 Entity Framework Core相关推荐
- 使用 ASP.NET Core, Entity Framework Core 和 ABP 创建N层Web应用 第二篇
介绍 这是"使用 ASP.NET Core ,Entity Framework Core 和 ASP.NET Boilerplate 创建N层 Web 应用"系列文章的第二篇.以下 ...
- 手把手引进门之 ASP.NET Core Entity Framework Core(官方教程翻译版 版本3.2.5)
以下是手把手引进门教程,基于 ASP.NET Core, Entity Framework Core ,ABP 框架 创建Web 应用, PS: 自带自动的测试模块哦. 样例下载 (上 github ...
- Entity Framework Core 2.0 使用入门
本文转载自作者:晓晨Master(李志强) 原文章地址 https://www.cnblogs.com/stulzq/p/7717873.html 一.前言 Entity Framework(后面简称 ...
- oracle精简版_使用Entity Framework Core访问数据库(Oracle篇)
前言 哇..看看时间 真的很久很久没写博客了 将近一年了. 最近一直在忙各种家中事务和公司的新框架 终于抽出时间来更新一波了. 本篇主要讲一下关于Entity Framework Core访问ora ...
- Entity Framework Core 5中实现批量更新、删除
本文介绍了一个在EntityFramework Core 5中不需要预先加载数据而使用一句SQL语句批量更新.删除数据的开发包,并且分析了其实现原理,并且与其他实现方案做了比较. 一.背景 随着微软全 ...
- 使用Entity Framework Core访问数据库(DB2篇)
上一篇讲了一些EF Core访问Oracle的坑.(感兴趣请移步:使用Entity Framework Core访问数据库(Oracle篇)) 这篇主要讲一下关于EF Core访问DB2的一揽子~问题 ...
- 使用Entity Framework Core访问数据库(Oracle篇)
前言 哇..看看时间 真的很久很久没写博客了 将近一年了. 最近一直在忙各种家中事务和公司的新框架 终于抽出时间来更新一波了. 本篇主要讲一下关于Entity Framework Core访问ora ...
- Entity Framework Core 之数据库迁移
前言 最近打算用.NET Core写一份开源的简易CMS系统,来练练手 所以又去深入研究了一下Entity Framework Core 发现其实有些细节园子里还是很少讲到. 特意整理了几个细节. 正 ...
- 全球首发免费的MySql for Entity Framework Core
Background 一时兴起,想实现.NET Core下的MySQL ADO层和与Entity Framework Core对接,同时也是非常鄙视某厂商借着目前Oracle官方没有对.NET Cor ...
最新文章
- Android ListView 自定义背景后 滚动时的背景变黑问题
- 怎么修复手机服务器,新手机怎么恢复旧手机上的所有数据?
- ABP官方文档翻译 6.1.1 MVC控制器
- 04 Websocket和Websocketed
- XV6700刷evdo详细教程
- 论文浅尝 | 利用 RNN 和 CNN 构建基于 FreeBase 的问答系统
- 阻塞式和非阻塞式udp传输_NIO非阻塞网络编程三大核心理念
- 什么是ZooKeeper
- Python练习:同符号数学运算
- 一文搞懂 CPU、GPU 和 TPU
- 从自卑的阴影中走出来
- 【面试】不容错过的12个深度学习面试问题
- LabVIEW在快速传输速率下丢失UDP数据包
- 面试百问:项目上线后才发现bug怎么办?
- Staring....
- 计算机学院举办 温暖冬日 感恩社会 活动,E·活动 | 我院举办“温暖冬日,感恩社会”活动...
- JAVA计算机毕业设计晨光文具店进销存系统设计与开发计算机(附源码、数据库)
- Java并发编程的艺术(推荐指数:☆☆☆☆☆☆)
- 猫哥教你写爬虫 000--开篇
- P4 开发实践 — Overview
热门文章
- Windows系统运维转linux系统运维的经历
- SpringMVC之Controller查找(Spring4.0.3/Spring5.0.4源码进化对比)
- 接口与object的关系
- GnuPG如何安全地分发私钥(1)GnuPG的用法
- 常用的rm,cp和mv命令
- [译] ASP.NET 生命周期 – ASP.NET 请求生命周期(四)
- 本日吐槽!“人傻钱多”的P2P公司是否是程序员的合适选择(群聊天记录的娱乐)...
- 用eclipse生成可运行jar包、启动jar包及常见错误
- 伍哥原创之豆荚商城商品搜索架构介绍
- Android 消息异步处理之AsyncTask