Entity Frame Code First 简易教程
一、简介
Entity Framework是微软的Object Relational Mapper(对象关系映射器),也就是我们平常说的ORM,它可以让应用程序开发者将关系型数据作为业务模型来使用。
Entity Framework分为 DabaBase First、Code First、Model First。本篇主要是结束Code First的一些应用。
- Database First:这是一种用于已存在数据库模式的方法。使用这种方法,EDM是从数据库模式中生成的,这种方法最适合于使用了已经存在的数据库的应用。
- Code First:这种方法中,所有的领域模型都是以类的形式编写的。这些类会建立我们的EDM,数据库模式会从这些类中创建。这种方法最适合于那些高度以领域为中心并且领域模型类创建优先的应用程序。这里需要的数据库只是为了这些领域模型的持久化机制。
- Model First:这种方法和Code First方法很相似,但是这种情况下我们使用了EDM视觉设计器来设计我们的模型。数据库模式和类将会通过这个概念模型生成。该模型将会给我们创建数据库的SQL语句,然后我们可以使用它来创建数据库并连接应用程序。
下面是使用Entity Framework的一些好处:
- 因为开发者不需要为数据访问编写所有需要的ADO.NET管道代码,因此这可以节省很多开发时间。
- 我们可以使用更高级的语言(例如C#)来编写所有的数据访问逻辑而不是编写SQL查询和存储过程。
- 因为数据库表没有高级的关系(如继承),然而领域实体是可以有的,所以业务模型(也就是概念模型)可以使用实体间的关系来适配应用领域。
- 底层的数据存储可以相对轻松地被取代,因为所有的数据访问逻辑都呈现在应用层而不是数据层。
二、什么是ORM
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。
简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
三、搭建Entity FrameWork CodeFirst应用
使用 Entity FrameWork必须引用 EntityFrameWork.DLL 文件,
可以通过VS 工具/NuGet管理器/命令控制台,在出现的命令窗口上输入 Install-Pageage EntityFramework 命令,回车自动安装。
在项目中创建 T_User 类
public class T_User
{
public T_User() { } /// <summary>
/// id
/// </summary>
[Required]
[Key]
public int Id { get; set; }
/// <summary>
/// 用户名
/// </summary>
[Required]
[MaxLength()]
public string UserName { get; set; }
/// <summary>
/// 账号
/// </summary>
[Required]
[MaxLength()]
public string Account { get; set; }
/// <summary>
/// Sex
/// </summary>
[Required]
public int Sex { get; set; }
/// <summary>
/// 密码
/// </summary>
[Required]
[MaxLength()]
[Column("Password", TypeName = "varchar")]
public string Password { get; set; }
/// <summary>
/// 地址
/// </summary>
[MaxLength()]
public string Address { get; set; }
/// <summary>
///
/// </summary>
[MaxLength()]
public string Memo { get; set; }
}
设置配置文件,配置数据库连接串
打开项目目录下的APP.Config,(按照项目的实际情况)因为我的项目是普通的类库,
假如你的项目是Web项目,那就配置在 Web.Config。配置数据库的用户名和密码
<connectionStrings>
<!-- 假如采用 Window连接方式,则取消注释采用第一个连接串
<add name="DBEntities" connectionString="Server=127.0.0.1;Database=MyDataBase;Integrated Security=SSPI" providerName="System.Data.SqlClient"/>
-->
<add name="DBEntities" connectionString="Server=127.0.0.1;Database=MyDataBase;uid=sa;password=123" providerName="System.Data.SqlClient"/>
</connectionStrings>
添加数据库上下文
接下来我们创建数据库上下文,它是数据库的抽象。目前,我们只有一张表T_User,因而要给该数据库上下文定义一个属性来代表这张表
再者,一张表中一般肯定不止一条数据行,所以我们必须定义一个集合属性,EF使用 DbSet
来实现这个目的。
新建 DBEntitys.CS 类文件(类名按照自己的需要),集成 DbContext 类。
在这里,DbContext 是所有基于EF的上下文基类,通过它可以访问到数据库中的所有表。
上面的代码中调用了父类的构造函数,并且传入了一个键值对,键是name,值是 DBEntities,也就是刚刚配置文件的数据库连接串的Name,
这个键值对是定义在应用程序的配置文件中的,取决于你的应用程序类型,可能是app.config或者web.config。在我们的 程序中就是App.config。
在app.config文件的configuration
的节点下(不要在第一个节点下,否则报错)添加:
public class DBEntitys : DbContext
{
public DBEntitys()
: base("DBEntities")
{ }
public virtual DbSet<T_User> T_User { get; set; }
}
做完上面的时候去以后,这个时候 咱们通过控制台程序去获取上下文对象里的T_User。
static void Main(string[] args)
{
using (var context = new DBEntitys())
{
context.Database.CreateIfNotExists();//如果数据库不存在时则创建
}
Console.Write("DB has Created!");//提示DB创建成功
Console.Read();
}
打开数据库,你会发现,EF帮我们自动创建了数据库和表
创建数据库的方式有两种:
- 下面我们会通过数据库迁移来实现数据库的创建。
- 通过EF数据库的API来创建。
四、数据库迁移
随着我们项目的进展,我们的数据库结构也可能发生改变时,我们可以使用EF本身来更新数据库。要使用这项技术,我们必须在项目上启用迁移(migration)。
首先我们把刚刚创建的数据删除。
打开 VS 工具/NubGet包管理器/程序包控制管理台,
1、默认项目选择刚才创建的项目 Entity(按照实际代码所在的项目),然后在窗口中输入 Enable-Migrations
,最后按下Enter键即可:
运行该命令后,我们会看到Data项目中多了一个名叫Migrations的文件夹,该文件夹里面有一个类,它指定了迁移配置,通过泛型参数将它连接到我们的数据库上下文。
2、然后在继续在窗口中输入 Add-Migrations migrations
,按下Enter键添加一个名为 FirstMigration 的迁移
3、执行 Update-DataBase
命令,更新数据库架构
如果更新数据库存在冲突而不能执行更新,可以添加 -Force强制执行,例如:“Update-Database -Force”
4、设置自动迁移
每次都通过控制台来进行迁移太过麻烦,可以设置为自动迁移。
打开 Migrations 文件夹下的 Configuration.CS文件,将 构造函数里的 AutomaticMigrationsEnabled=false; 改成 True
执行 Update-DataBase -Force
命令,更新数据库架构
有以下两个参数可以对自动迁移进行设置:
1. AutomaticMigrationsEnabled:获取或设置 指示迁移数据库时是否可使用自动迁移的值。
2. AutomaticMigrationDataLossAllowed:获取或设置 指示是否可接受自动迁移期间的数据丢失的值。如果设置为false,则将在数据丢失可能作为自动迁移一部分出现时引发异常
-------------------------------------------- 注意! ----------------------------------------------------------------------------
默认 Configuration() 方法里只有 AutomaticMigrationsEnabled = true;将 true改为 false,
然后添加 AutomaticMigrationDataLossAllowed = false;
以后再更新模型的时候,直接执行命令 Update-DataBase
命令,更新数据库架构即可。
internal sealed class Configuration : DbMigrationsConfiguration<Entity.DBEntitys>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = false;
} protected override void Seed(Entity.DBEntitys context)
{
// This method will be called after migrating to the latest version. // You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data.
}
}
5、数据库回滚
假如我们需要将数据库还原到之前的某个迁移版本,还是可以通过命令完成 Update-DataBase -TargetMigration:
命令,Migration
Version
填写迁移的版本:打开生成的数据库里面有个__MigrationHistory表,选择主键即可。Migration
Version
如果你想回滚一切至空数据库,可以使用 Update-DataBase -TargetMigration:
命令。$initialDataBase
五、表属性常见配置
EF Code-First提供了一组DataAnnotation属性,您可以将其应用于您的域类和属性。 DataAnnotation属性覆盖默认的Code-First约定。
System.ComponentModel.DataAnnotations | |
Key | 映射到相关表的主键 |
Timestamp | 不为空的时间戳列 |
Required | 必填 |
MinLength | 最小长度 |
MaxLength | 最大长度,也是设置数据库列的最大长度 |
StringLength | 字符串长度 |
System.ComponentModel.DataAnnotations.Schema | |
Table | 指定将与该类映射的DB表的名称 |
Column | 指定要与属性映射的列名称和数据类型 |
ForeignKey | 指定导航属性的外键属性 |
public class T_User
{
public T_User() { } /// <summary>
/// id
/// </summary>
[Required]
[Key]
public int Id { get; set; }
/// <summary>
/// 用户名
/// </summary>
[Required]
[MaxLength()]
public string UserName { get; set; }
/// <summary>
/// 账号
/// </summary>
[Required]
[MaxLength()]
public string Account { get; set; }
/// <summary>
/// Sex
/// </summary>
[Required]
public int Sex { get; set; }
/// <summary>
/// 密码
/// </summary>
[Required]
[MaxLength()]
[Column("Password", TypeName = "varchar")]
public string Password { get; set; }
/// <summary>
/// 地址
/// </summary>
[MaxLength()]
public string Address { get; set; }
/// <summary>
///
/// </summary>
[MaxLength()]
public string Memo { get; set; }
/// <summary>
/// 班级
/// </summary>
public int GradeId { get; set; }
/// <summary>
/// 班级
/// </summary>
[ForeignKey("GradeId")]
public virtual T_Grade T_Grade { get; set; }
}
六、Entity FrameWork 一对多、多对多
在平时的开发工作中,经常有多表查询,表和表之前的关系有单表查询、一对多查询、多对多查询。
1、一对多
例:在学校里有很多学生,每个学生是一个用户,每个用户都所属一个班级。班级和用户是一对多的关系。下面通过 Code First 实现一对多查询
学生类:
public class T_User
{
public T_User() { } /// <summary>
/// id
/// </summary>
[Required]
[Key]
public int Id { get; set; }
/// <summary>
/// 用户名
/// </summary>
[Required]
[MaxLength()]
public string UserName { get; set; }
/// <summary>
/// 账号
/// </summary>
[Required]
[MaxLength()]
public string Account { get; set; }
/// <summary>
/// Sex
/// </summary>
[Required]
public int Sex { get; set; }
/// <summary>
/// 密码
/// </summary>
[Required]
[MaxLength()]
[Column("Password", TypeName = "varchar")]
public string Password { get; set; }
/// <summary>
/// 地址
/// </summary>
[MaxLength()]
public string Address { get; set; }
/// <summary>
///
/// </summary>
[MaxLength()]
public string Memo { get; set; }
/// <summary>
/// 班级
/// </summary>
public int GradeId { get; set; }
/// <summary>
/// 班级
/// </summary>
[ForeignKey("GradeId")]
public virtual T_Grade T_Grade { get; set; }
}
班级类:
/// <summary>
/// 班级表
/// </summary>
public class T_Grade
{
public T_Grade()
{
T_User = new HashSet<T_User>();
}
/// <summary>
/// id
/// </summary>
[Key]
public int Id { get; set; }
/// <summary>
/// 班级名字
/// </summary>
public string GradeName { get; set; }
/// <summary>
/// 班级编号
/// </summary>
public string GradeCode { get; set; } /// <summary>
/// 用户
/// </summary>
public virtual ICollection<T_User> T_User { get; set; }
}
配置DBContext
public class DBEntitys : DbContext
{
public DBEntitys()
: base("DBEntities")
{
this.Configuration.LazyLoadingEnabled = false; //是否开启懒加载 [false/关闭]
}
public DBEntitys(string ConnStr)
: base(ConnStr)
{ }
public virtual DbSet<T_User> T_User { get; set; }
public virtual DbSet<T_Grade> T_Grade { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<T_User>()
.HasRequired<T_Grade>(a => a.T_Grade)
.WithMany(a => a.T_User);
}
}
执行数据库迁移命令以后,生成的表如下:
添加数据进行测试
class Program
{
public static readonly DBEntitys context = new DBEntitys();
static void Main(string[] args)
{
AddData(); //添加数据
var model = context.T_Grade.FirstOrDefault();
foreach (var item in model.T_User)
{
Console.WriteLine("Name:" + item.UserName);
}
Console.Read();
}
/// <summary>
/// 添加数据
/// </summary>
private static void AddData()
{
T_Grade t_Grade = new T_Grade() { GradeName = "一年级", GradeCode = "" };
context.T_Grade.Add(t_Grade);
//一个班级对应两个用户
T_User t_User = new T_User() { UserName = "User1", Account = "admin", Sex = , Password = "", GradeId = t_Grade.Id };
T_User t_User2 = new T_User() { UserName = "User2", Account = "", Sex = , Password = "", GradeId = t_Grade.Id };
context.T_User.Add(t_User);
context.T_User.Add(t_User2);
int row = context.SaveChanges();
Console.Write("数据添加成功");//提示DB添加成功
}
}
2、多对多
在学校里,一个(用户)学生可能有多门课程。同样,一门课程可能有多个(用户)学生选择。
(用户)学生和课程就是多对多的关系。即 ICollection<T_User> t_User 和 ICollection<T_Courses> t_Courses。
public class T_User
{
public T_User()
{
t_Courses = new HashSet<T_Courses>();
} /// <summary>
/// id
/// </summary>
[Required]
[Key]
public int Id { get; set; }
/// <summary>
/// 用户名
/// </summary>
[Required]
[MaxLength()]
public string UserName { get; set; }
/// <summary>
/// 账号
/// </summary>
[Required]
[MaxLength()]
public string Account { get; set; }
/// <summary>
/// Sex
/// </summary>
[Required]
public int Sex { get; set; }
/// <summary>
/// 密码
/// </summary>
[Required]
[MaxLength()]
[Column("Password", TypeName = "varchar")]
public string Password { get; set; }
/// <summary>
/// 地址
/// </summary>
[MaxLength()]
public string Address { get; set; }
/// <summary>
///
/// </summary>
[MaxLength()]
public string Memo { get; set; }
/// <summary>
/// 一个用户有多门课
/// </summary>
public virtual ICollection<T_Courses> t_Courses { get; set; }
}
/// <summary>
/// 课程类
/// </summary>
public class T_Courses
{
public T_Courses()
{
t_User = new HashSet<T_User>();
}
/// <summary>
/// 主键ID
/// </summary>
[Key]
public int Id { get; set; }
/// <summary>
/// 课程名
/// </summary>
[MaxLength(),Column(TypeName="varchar")]
public string CourseName { get; set; }
/// <summary>
/// 一门课有多个用户
/// </summary>
public virtual ICollection<T_User> t_User { get; set; }
}
执行数据库迁移命令以后生成的数据表如下:
使用配置Fluent API配置多对多关系:
public class DBEntitys : DbContext
{
public DBEntitys()
: base("DBEntities")
{
this.Configuration.LazyLoadingEnabled = true; //是否开启懒加载 [false/关闭]
}
public DBEntitys(string ConnStr)
: base(ConnStr)
{ }
public virtual DbSet<T_User> T_User { get; set; }
public virtual DbSet<T_Courses> T_Courses { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<T_User>()
.HasMany<T_Courses>(a => a.t_Courses)
.WithMany(a => a.t_User)
.Map(a =>
{
a.MapLeftKey("UserId");
a.MapRightKey("CourseId");
a.ToTable("User_Course");
});
}
}
执行测试:
class Program
{
public static readonly DBEntitys context = new DBEntitys();
static void Main(string[] args)
{
//AddData(); //添加数据
var model = context.T_User.FirstOrDefault();
foreach (var item in model.t_Courses)
{
Console.WriteLine("CourseName:" + item.CourseName);
}
Console.Read();
}
/// <summary>
/// 添加数据
/// </summary>
private static void AddData()
{
T_Courses chinese = new T_Courses() { CourseName = "语文" };
T_Courses math = new T_Courses() { CourseName = "数学" };
//一个班级对应两个用户
T_User t_User = new T_User() { UserName = "User1", Account = "admin", Sex = , Password = "" }; t_User.t_Courses.Add(chinese);
t_User.t_Courses.Add(math);
context.T_User.Add(t_User);
int row = context.SaveChanges();
Console.Write("数据添加成功");//提示DB添加成功
}
}
Entity Frame Code First 简易教程的更多相关文章
- Flow简易教程——安装篇
.mydoc_h1{ margin: 0 0 1em; } .mydoc_h1_a{ color: #2c3e50; text-decoration: none; font-size: 2em; } ...
- 文件上传利器SWFUpload入门简易教程
凡做过网站开发的都应该知道表单file的确鸡肋. Ajax解决了不刷新页面提交表单,但是却没有解决文件上传不刷新页面,当然也有其它技术让不刷新页面而提交文件,该技术主要是利用隐藏的iFrame, 较A ...
- Ant 简易教程
转载:http://www.cnblogs.com/jingmoxukong/p/4433945.html Ant 简易教程 Apache Ant,是一个将软件编译.测试.部署等步骤联系在一起加以自动 ...
- 使用 Entity Framework Code First
使用 Entity Framework Code First 在家闲着也是闲着,继续写我的[ASP.NET MVC 小牛之路]系列吧.在该系列的上一篇博文中,在显示书本信息列表的时候,我们是在程序代码 ...
- Intellj IDEA 简易教程
Intellj IDEA 简易教程 目录 JDK 安装测试 IDEA 安装测试 调试 单元测试 重构 Git Android 其他 参考资料 Java开发IDE(Integrated Developm ...
- Android开发简易教程
Android开发简易教程 Android 开发因为涉及到代码编辑.UI 布局.打包等工序,有一款好用的IDE非常重要.Google 最早提供了基于 Eclipse 的 ADT 作为开发工具,后来在2 ...
- [转]Unity3D Editor 编辑器简易教程
Star 自定义编辑器简易教程 an introduction to custom editors 原文地址 http://catlikecoding.com/unity/tutorials/star ...
- WebGL简易教程(十三):帧缓存对象(离屏渲染)
目录 1. 概述 2. 示例 2.1. 着色器部分 2.2. 初始化/准备工作 2.2.1. 着色器切换 2.2.2. 帧缓冲区 2.3. 绘制函数 2.3.1. 初始化顶点数组 2.3.2. 传递非 ...
- Docker之Ubuntu上使用Docker的简易教程
Ubuntu上使用Docker的简易教程 原始文档:https://www.yuque.com/lart/linux/fp6cla 说在开头 在天池的比赛中涉及到了docker的使用.经过多番探究,大 ...
随机推荐
- Matlab_audiowrite_音频生成
输出音频文件所需函数为 audiowrite .通过例程进行解释: % 生成时间序列 fs = 5000; % [Hz] 信号采样频率 T = 1; % [s] 信号长度 x = 0:1/fs:T; ...
- Open Nginx gzip
默认情况下,Nginx的gzip压缩是关闭的, gzip压缩功能就是可以让你节省不少带宽,但是会增加服务器CPU的开销哦,Nginx默认只对text/html进行压缩 ,如果要对html之外的内容进行 ...
- Beta版——爱阅APP功能说明书
爱阅APP功能说明书 一.引言 通过Alpha发布和一些用户的反馈信息,了解到我们APP存在的问题.针对这些问题我们做了一些修改.以下内容是Beta版的功能说明书. 二.工具 安卓手机 爱阅APP安装 ...
- 【转载】 强化学习(十)Double DQN (DDQN)
原文地址: https://www.cnblogs.com/pinard/p/9778063.html ------------------------------------------------ ...
- Linux_x86下NX与ASLR绕过技术(续)
四.Stack Canaries 首先看一下Stack Canaries演进历史: Stack Guard 是第一个使用 Canaries 探测的堆栈保护实现,它于 1997 年作为 GCC 的一个扩 ...
- windows server 2012启动进入cmd解决方法
感谢网友http://sns.yhjy.cn/u/XperiaZ/Blog/t-4748 由于删除了framework 4.5引起的. windows server 2012默认安装framework ...
- Parsing with Compositional Vector Grammars--paper
这篇和2012年的区别: 1)Max-Margin Training Objective J中RNN变为了CVG 2012-两个词向量合并并打分,这个-两个(词向量,POS)合并并打分 2012年: ...
- 解决插值表达式闪烁问题 - v-cloak
v-cloak页面在js没有加载出来的时候,不显示该部分 linux可以通过响应式设计模式,来模拟2,3G网络 <!DOCTYPE html><html><head> ...
- 13.python错误和异常
一.错误和异常1.程序中的错误分为俩种:(1)语法错误:不按照语言的规则,必须在程序执行前就改正(2)逻辑错误2.异常就是程序运行时发生错误的信号,分为三部分(1)Traceback:异常追踪的信息( ...
- WPF项目中解决ConfigurationManager不能用(转)
https://blog.csdn.net/MOESECSDN/article/details/78107888 在WPF项目中遇到这样的问题,做一下笔记.希望对自己和读者都有帮助. 在aap.con ...