Entity Framework Core

介绍

  Abp.EntityFrameworkCorenuget包用来集成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工程中定义自定义仓储类。

返回主目录

ABP官方文档翻译 9.2 Entity Framework Core的更多相关文章

  1. ABP 教程文档 1-1 手把手引进门之 ASP.NET Core & Entity Framework Core(官方教程翻译版 版本3.2.5)

    本文是ABP官方文档翻译版,翻译基于 3.2.5 版本 官方文档分四部分 一. 教程文档 二.ABP 框架 三.zero 模块 四.其他(中文翻译资源) 本篇是第一部分的第一篇. 第一部分分三篇 1- ...

  2. [Abp 源码分析]七、仓储与 Entity Framework Core

    0.简介 Abp 框架在其内部实现了仓储模式,并且支持 EF Core 与 Dapper 来进行数据库连接与管理,你可以很方便地通过注入通用仓储来操作你的数据,而不需要你自己来为每一个实体定义单独的仓 ...

  3. NET Core & Entity Framework Core

    ABP 教程文档 1-1 手把手引进门之 ASP.NET Core & Entity Framework Core(官方教程翻译版 版本3.2.5)   本文是ABP官方文档翻译版,翻译基于 ...

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

    from:http://www.1234.sh/post/pomelo-data-mysql?utm_source=tuicool&utm_medium=referral Source 源代码 ...

  5. Entity Framework Core 2.0 使用入门

    一.前言 Entity Framework(后面简称EF)作为微软家的ORM,自然而然从.NET Framework延续到了.NET Core.以前我也嫌弃EF太重而不去使用它,但是EF Core(E ...

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

    数据过滤器 介绍 预定义过滤器 ISoftDelete 何时使用? IMustHaveTenant 何时使用? IMayHaveTenant 何时使用 禁用过滤器 关于using语句 关于多租户 全局 ...

  7. Entity Framework Core 之数据库迁移

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

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

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

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

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

随机推荐

  1. Gym 100952F&&2015 HIAST Collegiate Programming Contest F. Contestants Ranking【BFS+STL乱搞(map+vector)+优先队列】

    F. Contestants Ranking time limit per test:1 second memory limit per test:24 megabytes input:standar ...

  2. HDU5135 dfs搜索 枚举种数

    Little Zu Chongzhi's Triangles Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/512000 ...

  3. c语言_FILE结构体解释及相关操作

    1. 文件和流的关系 C将每个文件简单地作为顺序字节流(如下图).每个文件用文件结束符结束,或者在特定字节数的地方结束,这个特定的字节数可以存储在系统维护的管理数据结构中.当打开文件时,就建立了和文件 ...

  4. [OpenCV学习笔记1][OpenCV基本数据类型]

    CvPoint基于二维整形坐标轴的点typedef struct CvPoint{int x; /* X 坐标, 通常以 0 为基点 */int y; /* y 坐标,通常以 0 为基点 */}CvP ...

  5. android studio升级2.3后出现的问题

    报错: Error:Execution failed for task ':app:javaPreCompileDebug'. > Annotation processors must be e ...

  6. 学而精计算机公共基础学习之路TEST2(程序设计基础)

    程序设计基础 程序设计方法与风格 1.程序设计方法 程序设计: 指设计.编制.调试程序的方法和过程. 程序设计方法是研究问题求解如何进行系统构造的软件方法学.常用的程序设计方法有:结构化程序设计方法. ...

  7. Yourphp系统发生错误

    今天早用YP更新缓存,弹出如下错误: 随之而来的是错误信息是: [php] view plain copy [14-12-03 10:48:12] E:\wwwweb\xmwszt360\Core\L ...

  8. 搭建mybatis时的小问题

    1.源文件中的xml文件经过编译后没有打包到classes中去,在源文件包中写的mapper文件运行时找不到. 解决办法: pom文件build下添加编译时加入xml和resource文件下的所有文件 ...

  9. 谁能教我iCloud怎么用?

    iCloud是苹果公司所提供的云端服务,使用者可以免费储存5GB的资料.你已经开始使用IOS5,并且你很兴奋的着手于将它同步至云服务层.以下就是怎样让你的设备更新至云服务层的非常简单的步骤.在你的iO ...

  10. 安装mysql后运行.net程序出错

    安装mysql后运行.net程序出错: 出错位置:C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config  出错信息:未 ...