上一篇写了《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. 2019-9-30-WPF-运行时迁移-EF-Core-数据库

    title author date CreateTime categories WPF 运行时迁移 EF Core 数据库 lindexi 2019-09-30 20:19:16 +0800 2019 ...

  2. Select multiple多选上移、下移

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD ...

  3. 接管SpringBoot对Activiti的数据源自动配置

    SpringBoot的自动配置真的让人又爱又恨,但还是爱更多一点. SpringBoot想要帮我们自动配置好一切,但是有时候配置的却并不是我们需要的,甚至有时候会默默的坑我们. 我的项目是一个多数据源 ...

  4. 【t001】不高兴的津津

    Time Limit: 1 second Memory Limit: 50 MB [问题描述] 津津上初中了.妈妈认为津津应该更加用功学习,所以津津除了上学之外,还要参加妈妈为她报名的各科复习班.另外 ...

  5. xUtils框架的介绍(二)

    xUtils中有四大组件可以供我们使用,分别是ViewUtils.HttpUtils.BitmapUtils以及DbUtils.如果你没能先读一下我的上一篇文章,那么请你移步过去先整体了解一下,再回过 ...

  6. tf.shape()

    tf.shapetf.shape( input, name=None, out_type=tf.int32)12345例如:将矩阵的维度输出为一个维度矩阵import tensorflow as tf ...

  7. maven环境隔离

    pom <build>节点下增加节点 <resources> <resource> <directory> src/main/resources.${d ...

  8. P1106 细胞分裂

    题目描述 Hanks博士是BT(Bio-Tech,生物技术)领域的知名专家.现在,他正在为一个细胞实验做准备工作:培养细胞样本. Hanks博士手里现在有 \(N\) 种细胞,编号从 \(1\) 到 ...

  9. 浅谈集合框架二 List、Set常用方法

    最近刚学完集合框架,想把自己的一些学习笔记与想法整理一下,所以本篇博客或许会有一些内容写的不严谨或者不正确,还请大神指出.初学者对于本篇博客只建议作为参考,欢迎留言共同学习. 之前有介绍集合框架的体系 ...

  10. 51nod 范德蒙矩阵

    思路: 根据矩阵乘法的定义,G中的第i行第j列的元素 ai,j ,对答案的贡献为 ai,j∗ T中第j行的所有元素之和. 因此我们可以将T中根据每行的和进行排序.第i行的和可以通过公式 (ai^n−1 ...