上一篇写了《Entity Farmework领域建模方式 3种编程方式》现在就Code First 继续学习

1、数据库表的创建

新建一个MVC的项目,在引用右击管理NuGet程序包,点击浏览搜索EF安装,我这里主要是EF6.0 以上的学习 所以都安装6.0 以上的版本

接下来在Model文件夹下面创建一个Customer类

 public class Customer
{
public int ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public DateTime AddTime { get; set; }
}

在创建一个继承EF上下文的类XXDBContext,(个人习惯XX是我的名字拼音缩写)此上下文是数据库交互的一个中间桥梁,我们称之为会话,并且为为一个模型公开一个DbSet。默认情况下EF链接LocalDB本地数据库(需要安装LocalDB实例),我还是手动通过EF上下文派生类的构造函数来配置数据库链接。下面我注释的是数据库初始化策略。我这里就选择始终创建数据库,后面用到配置表关联与字段的配置。

public class WYDBContext:DbContext
{
public WYDBContext(string ConnectionName) : base(ConnectionName) { }
public WYDBContext():base("SqlConn")
{
//默认的初始化器。这种初始化器在第一次运行程序时会创建数据库,再次运行不会再创建新的数据库。但是如果我们改变了领域类,运行程序时会抛出一个异常
//Database.SetInitializer(new CreateDatabaseIfNotExists<WYDBContext>()); //如果领域类发生了改变,删除以前的数据库,然后重建一个新的。采用这种初始化器不用再担心领域类改变影响数据库架构的问题。
//Database.SetInitializer(new DropCreateDatabaseIfModelChanges<WYDBContext.cs>()); //每次运行程序都会删除以前的数据库,重建新的数据库。如果在开发过程中每次都想使用最新的数据库,那么可以采用这种初始化器。
Database.SetInitializer(new DropCreateDatabaseAlways<WYDBContext>()); //禁用数据库初始化策略
//Database.SetInitializer<WYDBContext>(null);
}
public DbSet<Customer> Customer { get; set; }
}

webconfig配置

<system.web>
<compilation debug="true" targetFramework="4.6.1" />
<httpRuntime targetFramework="4.6.1" />
</system.web> <!--数据库连接-->
<connectionStrings>
<!--数据库连接ef字符串-->
<add name="SqlConn" connectionString="Data Source=地址;Initial Catalog=数据库名;Persist Security Info=True;User ID=用户名;Password=密码;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
</connectionStrings>

现在如果直接启动项目数据库是不会被创建的,只有调用到才会创建,在Home控制器的Index中调用,启动就生成了数据库

public ActionResult Index()
{
using (var db =new WYDBContext())
{
db.Customer.ToList();
}
return View();
}

2、 三者约定之 Code First约定(三者优先级 Fluent API > Data Annotations > 约定)

上面可已看出表Customer自己生成了主键ID。所谓约定,类似于C#中的接口,它是一个规范或者规则。使用Code First基于类定义通过约定来配置概念模型并以此为规则,约定就是基本规则。

Code First根据模型中定义的ID(不区分大小写),或者是以类名加ID的属性推断这样的属性为ID,如果为int或者guid类型,那么主键映射成标识列(自增长)。

Model下面在创建一个订单Order类一个客户有多个订单一个订单只能属于某一个客户这样客户与订单的关系就是一对多

 public class Order
{
public int ID { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Remark { get; set; }
public int CustomerID { get; set; }
/// <summary>
/// 订单对应的客户信息
/// </summary>
public virtual Customer Customer { get; set; }
} public class Customer
{
public int ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public DateTime AddTime { get; set; }
/// <summary>
/// 客户对应的订单信息
/// </summary>
public virtual IList<Order> Order { get; set; }
}

数据库上下文WYDBContext加上 public DbSet<Order> Order { get; set; } 刚刚加的订单类,运行起来 如果数据库删除不了的 自己闪一下 (在navicat 里面使用会这样,我就换在SSMS里面用)

它也生成了表与表的对应关系,然而string类型的你会发现字段都是max这肯定不行。接下来看Data Annatations 配置

3、三者约定之 Data Annotations

Data Annotations我的理解就是在字段类名上面加特性注解来控制字段属性的 栗子如下  还是Order与Customer两张表 记得添加命名空间using System.ComponentModel.DataAnnotations;跟using System.ComponentModel.DataAnnotations.Schema;

public class Customer
{
/// <summary>
/// ID
/// </summary>
[Key]//标识次列为主键
[Column("Zj", Order = , TypeName = "int")]//列名Zj,数据库序号0,类型int
[Required()]//不允许为空
[Display(Name = "Zj")]//显示名称,这里大多都是中文 后面视图@Html.DisplayNameFor(item=> model.Name)用到 显示的
public int Zj { get; set; }
/// <summary>
/// 姓名
/// </summary>
[Column("NameWYY", TypeName = "nvarchar")]//我加了WYY看效果
[StringLength(, ErrorMessage = "{0}长度不能超过50个字符")]
[Display(Name = "姓名")]
public string Name { get; set; }
/// <summary>
/// 年龄
/// </summary> [Column("Age", TypeName = "int")]
[Display(Name = "年龄")]
public int? Age { get; set; }//加了?允许为null
/// <summary>
/// 邮箱
/// </summary>
[Column("Email", TypeName = "nvarchar")]
[StringLength(, ErrorMessage = "{0}长度不能超过50个字符")]
[Display(Name = "电子邮箱")]
public string Email { get; set; }
/// <summary>
/// 日期
/// </summary>
[Column("AddTime", TypeName = "datetime2")]//如果不定义datetime2添加DateTime.Now就会报错哦
[Display(Name = "添加日期")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")]//日期格式化
public DateTime AddTime { get; set; }
/// <summary>
/// 客户对应的订单信息
/// </summary>
public virtual IList<Order> Order { get; set; }
} // [NotMapped]//表不映射到数据库
[Table("Tb_Order")]//表名
public class Order
{
/// <summary>
/// ID
/// </summary>
[Key]
[Column("ID", Order = , TypeName = "int")]
[Required()]
[Display(Name = "ID")]
public int ID { get; set; }
/// <summary>
/// 名称
/// </summary>
[Column("Name", TypeName = "nvarchar")]
[StringLength(, ErrorMessage = "{0}长度不能超过50个字符")]
[Display(Name = "名称")]
public string Name { get; set; }
/// <summary>
/// 价格
/// </summary>
[Column("Price")]
[Display(Name = "价格")]
public decimal? Price { get; set; }
/// <summary>
/// 备注
/// </summary>
[StringLength()]//长度约束
[Column("Remark", TypeName = "nvarchar")]//我加了WYY看效果
[Display(Name = "备注")]
public string Remark { get; set; }
/// <summary>
/// 客户ID
/// </summary>
[ForeignKey("Customer")]//外键
public int CustomerID { get; set; }
/// <summary>
/// 订单对应的客户信息
/// </summary>
[ForeignKey("CustomerID")]//外键
public virtual Customer Customer { get; set; } /// <summary>
/// 不映射字段
/// </summary>
[NotMapped]//不映射到数据库
public string XXX { get; set; }
}

4、三者约定之 Fluent API

这个就要在派生类重写OnModelCreating了  少一点 的表还可以在里面设置各个字段多了还是映射Map在模型表里面写,在OnModelCreatiing注册模型类就可以了;

 public DbSet<Customer> Customer { get; set; }
public DbSet<Order> Order { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//TODO 配置映射
modelBuilder.Entity<Customer>().ToTable("CSTo");//数据库表名
modelBuilder.Entity<Customer>().HasKey(x => x.Zj);//主键
modelBuilder.Entity<Customer>().Property(x=>x.AddTime).HasColumnType("DATETIME2");//时间
modelBuilder.Entity<Customer>().Property(x=>x.Age).IsOptional();//为null
//HasColumnType("DATETIME2(7)")这种写是错的
modelBuilder.Entity<Customer>().Property(x => x.Name).IsRequired().HasColumnType("varchar").HasMaxLength();//不为空,类型,长度 //默认情况下不会生成复数的表 如Orders
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Configurations.Add(new OrderMap());//注册
base.OnModelCreating(modelBuilder); } // [NotMapped]//表不映射到数据库
[Table("Tb_Order")]//表名
public class Order
{
///字段 }
public class OrderMap : EntityTypeConfiguration<Order>
{
public OrderMap()
{
//对应数据库表名
this.ToTable("ORd");
//一个订单必须对应有一个客户,客户一对多(订单) 用户表里面的 CustomerID
this.HasRequired(p => p.Customer).WithMany(p => p.Order).HasForeignKey(p => p.CustomerID);
this.HasKey(k => k.ID);//主键
this.Property(p => p.Name).HasColumnType("VARCHAR").HasMaxLength().IsRequired();//Name字段属性(varchar,长度50,不为null)
this.Property(p => p.Remark).HasColumnType("VARCHAR").HasMaxLength().IsOptional();//Remark(varchar,长度5000,null)
this.Property(p => p.Price).HasColumnName("pp");//列名
}
}

C#的数值类型对应数据库如下

●C#中的 int类型默认映射后对应数据库中的int类型。

● C#中的double类型默认映射后对应数据库中的float类型

●C#中的float类型默认映射后对应数据库中的real类型。

●C#中 的decimal类型默认映射后对应数据库中的decimal(18,2)类型

●C#中 的Int64类型默认映射后对应数据库中的bigint类型。

一般都是用Data Anntations  跟默认的约定好久没用记录一下  用到又来拿  Fluent API也是好久没复习了 哈哈 有时间在看看书

EF 学习系列二 数据库表的创建和表关系配置(Fluent API、Data Annotations、约定)的更多相关文章

  1. windows下mongodb基础玩法系列二CURD操作(创建、更新、读取和删除)

    windows下mongodb基础玩法系列 windows下mongodb基础玩法系列一介绍与安装 windows下mongodb基础玩法系列二CURD操作(创建.更新.读取和删除) windows下 ...

  2. MyBatis学习系列二——增删改查

    目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring 数据库的经典操作:增删改查. 在这一章我们主要说明一下简单的查询和增删改, ...

  3. scrapy爬虫学习系列二:scrapy简单爬虫样例学习

    系列文章列表: scrapy爬虫学习系列一:scrapy爬虫环境的准备:      http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_00 ...

  4. [转]ASP.NET MVC学习系列(二)-WebAPI请求 传参

    [转]ASP.NET MVC学习系列(二)-WebAPI请求 传参 本文转自:http://www.cnblogs.com/babycool/p/3922738.html ASP.NET MVC学习系 ...

  5. RabbitMQ学习系列二-C#代码发送消息

    RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列 http://www.80iter.com/blog/1437455520862503 上一篇已经讲了Rabbi ...

  6. 图机器学习(GML)&图神经网络(GNN)原理和代码实现(前置学习系列二)

    项目链接:https://aistudio.baidu.com/aistudio/projectdetail/4990947?contributionType=1 欢迎fork欢迎三连!文章篇幅有限, ...

  7. [Unity3D插件]2dtoolkit系列二 动画精灵的创建以及背景图的无限滚动

    经过昨天2dtoolkit系列教程一的推出,感觉对新手还有有一定的启发作用,引导学习使用unity 2dToolKit插件的使用过程,今天继续系列二——动画精灵的创建,以及背景图的无限循环滚动,在群里 ...

  8. .net reactor 学习系列(二)---.net reactor界面各功能说明

    原文:.net reactor 学习系列(二)---.net reactor界面各功能说明         安装了.net reactor之后,可以在安装目录下找到帮助文档REACTOR_HELP.c ...

  9. Spring5.0源码学习系列之浅谈BeanFactory创建

    Spring5.0源码学习系列之浅谈BeanFactory创建过程 系列文章目录 提示:Spring源码学习专栏链接 @ 目录 系列文章目录 博客前言介绍 一.获取BeanFactory主流程 二.r ...

随机推荐

  1. Android教程 -04 启动其它Activity,静态工厂设计模式传递数据

    视频建议采用超清模式观看, 欢迎点击订阅我的优酷 意图 Intent 一个应用程序肯定不只有一个界面,如何切换到其它界面,只时候就需要启动其它的Activity.启动Activity有多种方式.我在这 ...

  2. 使用FormData格式上传图像并预览图片

    前言 做项目时,遇到表单中图像需要跟表单一起提交,这样会造成后台没办法接收到图片.后面上网调查后,明白表单提交时是默认application/x-www-form-urlencoded格式,只接受键值 ...

  3. C# Dapper 基本使用 增删改查事务

    来源:https://blog.csdn.net/Tomato2313/article/details/78880969 using DapperTest.Models; using System.C ...

  4. hdu 1595 find the longest of the shortest(迪杰斯特拉,减去一条边,求最大最短路)

    find the longest of the shortest Time Limit: 1000/5000 MS (Java/Others)    Memory Limit: 32768/32768 ...

  5. poj 3384 Feng Shui (Half Plane Intersection)

    3384 -- Feng Shui 构造半平面交,然后求凸包上最远点对. 这题的题意是给出一个凸多边形区域,要求在其中放置两个半径为r的圆(不能超出凸多边形区域),要求求出两个圆心,使得多边形中没有被 ...

  6. springboot activiti工作流简单示例

    最近一直研究springboot,根据工作需求,工作流需要作为一个单独的微服务工程来提供给其他服务调用,现在简单的写下工作流(使用的activiti)微服务的搭建与简单使用 jdk:1.8 数据库:m ...

  7. HDU 1072

    题意:给你一个迷宫,2代表你当前的位置,0代表墙,1代表可走的路,3代表出口,4代表的是炸弹的重置点,一开始炸弹的倒计时设置为6,每走一步时间减少1,倒计时到0的时候走到3或者4都不可以,问走出迷宫的 ...

  8. 再一次利用with as 优化SQL

    上海的一个哥们问我有个SQL跑了4个小时都没跑完,实在受不了了,找我优化一下.我确实挺佩服他的,要是我遇到跑了几分钟的,就受不了了. SQL语句和执行计划如下: --sql id:1qbbw3th4x ...

  9. Python--day42--mysql创建用户及授权

    1,打开mysql数据库命令:mysql -u root -p 2,创建数据库create database db2; 2,删除数据库drop database db2; 2,展示有多少个文件夹:sh ...

  10. 【9101】求n!的值

    Time Limit: 10 second Memory Limit: 2 MB 问题描述 用高精度的方法,求n!的精确值(n的值以一般整数输入). Input 文件输入仅一行,输入n. Output ...