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相关推荐

  1. 使用 ASP.NET Core, Entity Framework Core 和 ABP 创建N层Web应用 第二篇

    介绍 这是"使用 ASP.NET Core ,Entity Framework Core 和 ASP.NET Boilerplate 创建N层 Web 应用"系列文章的第二篇.以下 ...

  2. 手把手引进门之 ASP.NET Core Entity Framework Core(官方教程翻译版 版本3.2.5)

    以下是手把手引进门教程,基于 ASP.NET Core, Entity Framework Core ,ABP 框架 创建Web 应用, PS: 自带自动的测试模块哦. 样例下载 (上 github  ...

  3. Entity Framework Core 2.0 使用入门

    本文转载自作者:晓晨Master(李志强) 原文章地址 https://www.cnblogs.com/stulzq/p/7717873.html 一.前言 Entity Framework(后面简称 ...

  4. oracle精简版_使用Entity Framework Core访问数据库(Oracle篇)

    前言 哇..看看时间 真的很久很久没写博客了 将近一年了. 最近一直在忙各种家中事务和公司的新框架  终于抽出时间来更新一波了. 本篇主要讲一下关于Entity Framework Core访问ora ...

  5. Entity Framework Core 5中实现批量更新、删除

    本文介绍了一个在EntityFramework Core 5中不需要预先加载数据而使用一句SQL语句批量更新.删除数据的开发包,并且分析了其实现原理,并且与其他实现方案做了比较. 一.背景 随着微软全 ...

  6. 使用Entity Framework Core访问数据库(DB2篇)

    上一篇讲了一些EF Core访问Oracle的坑.(感兴趣请移步:使用Entity Framework Core访问数据库(Oracle篇)) 这篇主要讲一下关于EF Core访问DB2的一揽子~问题 ...

  7. 使用Entity Framework Core访问数据库(Oracle篇)

    前言 哇..看看时间 真的很久很久没写博客了 将近一年了. 最近一直在忙各种家中事务和公司的新框架  终于抽出时间来更新一波了. 本篇主要讲一下关于Entity Framework Core访问ora ...

  8. Entity Framework Core 之数据库迁移

    前言 最近打算用.NET Core写一份开源的简易CMS系统,来练练手 所以又去深入研究了一下Entity Framework Core 发现其实有些细节园子里还是很少讲到. 特意整理了几个细节. 正 ...

  9. 全球首发免费的MySql for Entity Framework Core

    Background 一时兴起,想实现.NET Core下的MySQL ADO层和与Entity Framework Core对接,同时也是非常鄙视某厂商借着目前Oracle官方没有对.NET Cor ...

最新文章

  1. Android ListView 自定义背景后 滚动时的背景变黑问题
  2. 怎么修复手机服务器,新手机怎么恢复旧手机上的所有数据?
  3. ABP官方文档翻译 6.1.1 MVC控制器
  4. 04 Websocket和Websocketed
  5. XV6700刷evdo详细教程
  6. 论文浅尝 | 利用 RNN 和 CNN 构建基于 FreeBase 的问答系统
  7. 阻塞式和非阻塞式udp传输_NIO非阻塞网络编程三大核心理念
  8. 什么是ZooKeeper
  9. Python练习:同符号数学运算
  10. 一文搞懂 CPU、GPU 和 TPU
  11. 从自卑的阴影中走出来
  12. 【面试】不容错过的12个深度学习面试问题
  13. LabVIEW在快速传输速率下丢失UDP数据包
  14. 面试百问:项目上线后才发现bug怎么办?
  15. Staring....
  16. 计算机学院举办 温暖冬日 感恩社会 活动,E·活动 | 我院举办“温暖冬日,感恩社会”活动...
  17. JAVA计算机毕业设计晨光文具店进销存系统设计与开发计算机(附源码、数据库)
  18. Java并发编程的艺术(推荐指数:☆☆☆☆☆☆)
  19. 猫哥教你写爬虫 000--开篇
  20. P4 开发实践 — Overview

热门文章

  1. Windows系统运维转linux系统运维的经历
  2. SpringMVC之Controller查找(Spring4.0.3/Spring5.0.4源码进化对比)
  3. 接口与object的关系
  4. GnuPG如何安全地分发私钥(1)GnuPG的用法
  5. 常用的rm,cp和mv命令
  6. [译] ASP.NET 生命周期 – ASP.NET 请求生命周期(四)
  7. 本日吐槽!“人傻钱多”的P2P公司是否是程序员的合适选择(群聊天记录的娱乐)...
  8. 用eclipse生成可运行jar包、启动jar包及常见错误
  9. 伍哥原创之豆荚商城商品搜索架构介绍
  10. Android 消息异步处理之AsyncTask