一、 EntirtyFramework(EF)简介

EntirtyFramework框架是一个轻量级的可扩展版本的流行实体框架数据访问技术,微软官方提供的ORM工具让开发人员节省数据库访问的代码时间,将更多的时间放到业务逻辑层代码上。EF提供变更跟踪、唯一性约束、惰性加载、查询事物等。开发人员使用Linq语言,对数据库操作如同操作Object对象一样省事。

EF有三种使用场景,1. 从数据库生成Class(DB First),2.由实体类生成数据库表结构(Code First),3.  通过数据库可视化设计器设计数据库,同时生成实体类(Model First)。

EF架构如下:

EDM (实体数据模型):EDM包括三个模型,概念模型、 映射和存储模型。

概念模型 ︰ 概念模型包含模型类和它们之间的关系。独立于数据库表的设计。

存储模型 ︰ 存储模型是数据库设计模型,包括表、 视图、 存储的过程和他们的关系和键。

映射 ︰ 映射包含有关如何将概念模型映射到存储模型的信息。

LINQ to Entities ︰ LINQ to Entities 是一种用于编写针对对象模型的查询的查询语言。它返回在概念模型中定义的实体。

Entity SQL: Entity SQL 是另一种炉类似于L2E的言语,但相给L2E要复杂的多,所以开发人员不得不单独学习它。

Object Services(对象服务):是数据库的访问入口,负责数据具体化,从客户端实体数据到数据库记录以及从数据库记录和实体数据的转换。

Entity Client Data Provider:主要职责是将L2E或Entity Sql转换成数据库可以识别的Sql查询语句,它使用Ado.net通信向数据库发送数据可获取数据。

ADO.Net Data Provider:使用标准的Ado.net与数据库通信。

二、EntirtyFrameworkCore(EF Core)

Entity Framework Core (EF Core) 是在 2016 年首次发布的 EF6 的完全重写。 它附带于 Nuget 包中,是 Microsoft.EntityFrameworkCore 的主要组成部分。 EF Core 是一种跨平台产品,可以在 .NET Core 或 .NET Framework 上运行。EF Core 提供了在 EF6 中不会实现的新功能(如备选键批量更新以及 LINQ 查询中的混合客户端/数据库评估。但由于它是一个新代码库,所以会缺少一些 EF6 中的功能。

EFCore与之前的EF基本类似,区别在于配置的时候有一些差异;支持DB First和Model First,广泛使用的Code First模式;EF Core2.1开始支持Lazy loading。

EFCore的数据库访问技术使用之前请先安装Microsoft.EntityFrameworkCore包

三、EF Core使用DB First

数据库优先(DB First),编码步骤如下:

1、新建数据库
       2、对模型实施反向工程
           Scaffold-DbContext [-Connection] <String> [-Provider] <String> [-OutputDir <String>] [-Context <String>]
           [-Schemas <String>] [-Tables <String>] [-DataAnnotations] [ -Force] [-Project <String>]
           [-StartupProject <String>] [-Environment <String>] [<CommonParameters>]
       3、在项目中配置数据库连接字符串。

 四、EF Core使用Code First

编码优先(Code First),执行步骤如下:

1、新建模型类
        2、新建DBContext
        3、在项目中配置数据库连接字符串
        4、执行如下命令(数据库迁移): Add-Migration [类名],     Update-Database

数据表级联,这里主要说一下级联删除

1、外键属性可为NULL的级联删除时外键属性直接设置为 null即可

2、外键属性不可为NULL级联删除时会引发异常,需要设置删除行为 DeleteBehavior ,DeleteBehavior 的类型如下表所示

数据加载是需要重点掌握的,EF的关联实体加载有三种方式:Lazy Loading,Eager Loading,Explicit Loading,其中Lazy Loading和Explicit Loading都是延迟加载。

(一)Lazy Loading(惰性加载)使用的是动态代理,默认情况下,如果POCO类满足以下两个条件,EF就使用Lazy Loading:

POCO类是Public且不为Sealed。导航属性标记为Virtual。

关闭Lazy Loading,可以将LazyLoadingEnabled设为false,如果导航属性没有标记为virtual,Lazy Loading也是不起作用的。

     /// <summary>
/// 用户信息表
/// </summary>
public class User
{
/// <summary>
/// 用户ID
/// </summary>
//[Key]
//[DatabaseGenerated(DatabaseGeneratedOption.Identity)] //设置自增
public int UserId { get; set; }
/// <summary>
/// 用户编码
/// </summary>
public string UserNo { get; set; }
/// <summary>
/// 用户名称
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 用户电话
/// </summary>
public string TelPhone { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
public virtual Orginazation Org { get; set; }
public virtual ICollection<UserAndRole> Roles { get; set; }
}

User实体类

 /// <summary>
/// 角色信息表
/// </summary>
public class Role
{
/// <summary>
/// 角色ID
/// </summary>
//[Key]
//[DatabaseGenerated(DatabaseGeneratedOption.Identity)] //设置自增
public int RoleID { get; set; }
/// <summary>
/// 角色编码
/// </summary>
public string RoleNO { get; set; }
/// <summary>
/// 角色名称
/// </summary>
public string RoleName { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
public virtual ICollection<UserAndRole> Users { get; set; }
}

Role实体类

  /// <summary>
/// 部门信息表
/// </summary>
public class Orginazation
{
//private readonly ILazyLoader _lazyLoader; //public Orginazation(ILazyLoader lazyLoader)
//{
// _lazyLoader = lazyLoader;
//} /// <summary>
/// 部门ID
/// </summary>
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] //设置自增
public int OrgId { get; set; }
/// <summary>
/// 部门编码
/// </summary>
public string OrgNO { get; set; }
/// <summary>
/// 部门名称
/// </summary>
public string OrgName { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
public virtual ICollection<User> Users { get; set; }
}

Orginazation实体类

UserAndRole

在.net Core2.0及以上版本中使用惰性加载需要引用惰性加载代理包,EF Core一般情况下使用惰性加载,因此为了避免报循环引用的异常需要设置ReferenceLoopHandling为Ignore

Install-package Microsoft.EntityFrameworkCore.Proxies 

Startup.cs文件显示使用惰性加载

 public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
}); services.AddDbContext<CodeFirstContext>(options =>
{
//注入数据库
options.UseSqlServer(Configuration.GetConnectionString("SqlServerConnStr")).ToString();
//打开延迟加载代理的创建。
options.UseLazyLoadingProxies();
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddJsonOptions(options =>
{
//由于使用了惰性加载,因此需要设置此参数避免报循坏引用的异常
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
}

Startup.cs

     public class HomeController : Controller
{
private readonly CodeFirstContext _dbContext;
public IConfiguration Configuration { get; }
string conn = string.Empty;
public HomeController(CodeFirstContext _context)
{
_dbContext = _context;
}
public IActionResult Index()
{
Role role = new Role
{
RoleNO = "",
RoleName = "管理员角色",
Remark = "所有权限"
};
Orginazation org = new Orginazation
{
OrgNO = "",
OrgName = "总公司",
Remark = "部门根节点"
};
User user = new User
{
UserNo = "admin",
UserName = "管理员",
Remark = "系统管理员",
TelPhone="",
Org = org
};
UserAndRole userAndRoleModel = new UserAndRole
{
Role = role,
User = user,
RoleID = role.RoleID,
UserId = user.UserId
};
user.Roles.Add(userAndRoleModel);
role.Users.Add(userAndRoleModel);
_dbContext.Roles.Add(role);
_dbContext.Orginazations.Add(org);
_dbContext.Users.Add(user);
_dbContext.UserAndRoles.Add(userAndRoleModel); _dbContext.SaveChanges(); //延迟加载
var orgs = _dbContext.Orginazations;
foreach (var userModel in orgs.FirstOrDefault().Users)
{
//删除部门用户
_dbContext.Users.Remove(userModel);
}
_dbContext.SaveChanges();
return View();
} public IActionResult About()
{
_dbContext.Roles.Add(new Role
{
RoleNO = "role1",
RoleName = "RoleName1",
Remark = "Remark1"
}); //删除用户,对应头像表里的数据也会被删除
var user = _dbContext.Users.First();
_dbContext.Users.Remove(user);
_dbContext.SaveChanges(); ViewData["Message"] = "Your application description page."; return View();
} public IActionResult Contact()
{
ViewData["Message"] = "Your contact page."; return View();
} public IActionResult Privacy()
{
return View();
} [ResponseCache(Duration = , Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}

HomeController

 /// <summary>
/// Code First编码上下文
/// </summary>
public class CodeFirstContext : DbContext
{
public CodeFirstContext(DbContextOptions<CodeFirstContext> conn)
: base(conn)
{
}
/// <summary>
/// 映射用户信息表
/// </summary>
public virtual DbSet<User> Users { get; set; }
/// <summary>
/// 映射部门信息表
/// </summary>
public virtual DbSet<Orginazation> Orginazations { get; set; }
/// <summary>
/// 映射角色信息表
/// </summary>
public virtual DbSet<Role> Roles { get; set; }
/// <summary>
/// 用户角色信息表
/// </summary>
public virtual DbSet<UserAndRole> UserAndRoles { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//用户
modelBuilder.Entity<User>(entity =>
{
entity.ToTable("User");
entity.Property(e => e.UserName).IsRequired().HasMaxLength();
entity.Property(e => e.UserNo).IsRequired().HasMaxLength();
entity.Property(e => e.TelPhone).HasMaxLength();
entity.Property(e => e.Remark).HasMaxLength();
entity.HasOne(u => u.Org).WithMany(r => r.Users).OnDelete(DeleteBehavior.SetNull); }); //角色
modelBuilder.Entity<Role>(entity =>
{
entity.ToTable("Role");
entity.Property(e => e.RoleName).IsRequired().HasMaxLength();
entity.Property(e => e.RoleNO).IsRequired().HasMaxLength();
entity.Property(e => e.Remark).HasMaxLength();
}); //部门信息
modelBuilder.Entity<Orginazation>(entity =>
{
entity.ToTable("Orginazation");
entity.Property(e => e.OrgNO).IsRequired().HasMaxLength();
entity.Property(e => e.OrgName).IsRequired().HasMaxLength();
entity.Property(e => e.Remark).HasMaxLength();
//多个用户对应一个部门
entity.HasMany(u => u.Users).WithOne(r => r.Org).OnDelete(DeleteBehavior.SetNull);
}); //用户角色信息表
modelBuilder.Entity<UserAndRole>(entity =>
{
entity.ToTable("UserAndRole");
entity.HasKey(ua => new { ua.RoleID, ua.UserId });
});
modelBuilder.Entity<UserAndRole>(entity =>
{
entity.ToTable("UserAndRole");
entity.HasOne(u => u.Role).WithMany(r => r.Users);
});
modelBuilder.Entity<UserAndRole>(entity =>
{
entity.ToTable("UserAndRole");
entity.HasOne(u => u.User).WithMany(r => r.Roles);
});
}
}

CodeFirstContext数据库上下文类

执行数据库迁移命令Add-Migration init22222结果如下:

更新数据库Update-Database,生成数据库表结果如下:

至此、Code First主要步骤完成了,通过Code First正确创建了表之间一对多和多对多的关系,本实例中User和Role是多对多的关系,User和Orginazation是多对一的关系,

(二)Eager Loading(预加载)使用Include方法关联预先加载的实体。在这里就不举例说明了。

(三)Explicit Loading(直接加载)使用Entry方法,对于集合使用Collection,单个实体则使用Reference。在这里就不举例说明了。

以上是我对Entity Framework Core的总结和使用,欢迎纠错!!!

Entity Framework (EF) Core工具创建一对多和多对多的关系的更多相关文章

  1. ASP.NET Core 开发 - Entity Framework (EF) Core

    EF Core 1.0 Database First http://www.cnblogs.com/linezero/p/EFCoreDBFirst.html ASP.NET Core 开发 - En ...

  2. Entity Framework (EF) Core学习笔记 1

    1. Entity Framework (EF) Core 是轻量化.可扩展.开源和跨平台的数据访问技术,它还是一 种对象关系映射器 (ORM),它使 .NET 开发人员能够使用面向对象的思想处理数据 ...

  3. ASP.NET Core 开发-Entity Framework (EF) Core 1.0 Database First

    ASP.NET Core 开发-Entity Framework Core 1.0 Database First,ASP.NET Core 1.0 EF Core操作数据库. Entity Frame ...

  4. 【极力分享】[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例【转载自https://segmentfault.com/a/1190000004152660】

      [C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例 本文我们来学习一下在Entity Framework中使用Cont ...

  5. 在Entity Framework 中用 Code First 创建新的数据库

    在Entity Framework 中用 Code First 创建新的数据库 (原文链接) 本文将逐步介绍怎样用Code First 创建新数据库,使用在代码中定义类和API中提供的特性(Attri ...

  6. Visual Studio Entity Framework (EF) 生成SQL 代码 性能查询

    Visual Studio Entity Framework (EF) 生成SQL 代码 性能查询     SQL 中,有SQL Server Profiler可以用来查询性能以及查看外部调用的SQL ...

  7. [转]Using Entity Framework (EF) Code-First Migrations in nopCommerce for Fast Customizations

    本文转自:https://www.pronopcommerce.com/using-entity-framework-ef-code-first-migrations-in-nopcommerce-f ...

  8. ADO.NET Entity Framework(EF)

    ylbtech-Miscellaneos: ADO.NET Entity Framework(EF) A,返回顶部 1, ADO.NET Entity Framework 是微软以 ADO.NET 为 ...

  9. ORM之Entity Framework(EF)

    ORM之Entity Framework(EF) 一.下载安装: nuget 搜索Entity Framework安装 EntityFramework.Extension是个扩展库根据需要安装 二.使 ...

随机推荐

  1. [Active Learning] Multi-Criteria-based Active Learning

    目录 1 Informativeness 2 Representativeness 3 Diversity 3.1 Global consideration 3.2 Local considerati ...

  2. 使用MediatR重构单体应用中的事件发布/订阅

    标题:使用MediatR重构单体应用中的事件发布/订阅 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/10640280.html 源代码:https ...

  3. 5.JAVA-内部类实例

    在JAVA中,类内部可以添加其它类,当然也可以实现类继承(后续章节学习). 本章示例-实现部门类和雇员类 可以通过部门对象,查找该部门的雇员信息. 可以通过雇员对象,查找该雇员所在的部门信息 代码如下 ...

  4. 《Jave并发编程的艺术》学习笔记(1-2章)

    Jave并发的艺术 并发编程的挑战 上下文切换 CPU通过时间片分配算法来循环执行任务,当前时间片执行完之后会切换到下一个任务.但是,切换会保存上一个任务的状态,一遍下次切换回这个任务时,可以再次加载 ...

  5. 将包含经纬度点位信息的Excel表格数据导入到ArcMap中并输出成shapefile

    将包含经纬信息的Excel表格数据,导入到ArcMap中并输出成shapefile,再进行后面的操作.使用这种方法可以将每一个包含经纬信息的数据在ArcMap中点出来. 一.准备数据 新建Excel表 ...

  6. 一起学Android之Menu

    概述 菜单(Menu)在Android开发中,是一种常见的用户界面组件,通过使用菜单Api可以给用户提供常见的一致的体验.本文主要讲解三种菜单的相关内容. 菜单的分类 选项菜单(OptionsMenu ...

  7. asp.net core重新加载应用配置

    asp.net core重新加载应用配置 Intro 我把配置放在了数据库或者是Redis里,配置需要修改的时候我要直接修改数据库,然后调用一个接口去重新加载应用配置,于是就尝试写一个运行时重新加载配 ...

  8. 关于inet_addr() 函数

    inet_addr() 将一个字符串格式的ip地址转换成一个uint32_t数字格式 但是需要注意的是, 这个函数的返回值在大小端机器上是不同的 例如输入一个"192.168.0.1&quo ...

  9. TTL 和 DNS TTL 的区别

    TTL TTL是 Time To Live 的缩写,该字段指定IP包被路由器丢弃之前允许通过的最大网段数量.TTL是IPv4包头的一个8 bit字段.在IPv4包头中TTL是一个8 bit字段,它位于 ...

  10. 解决ASP.NET Core MVC调试慢的问题

    最近在做的一个项目中,发现网页端同时发起了4个AJAX请求需要数秒才获取到响应,太慢了,当我把请求数降低为1个的时候,速度看起来就比较正常,增加到2个同时的请求后,速度就有些慢了,3个的话就明显慢了, ...