上一篇写了《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. [***]HZOI20190714 T2熟练剖分

    这题真的神仙,蒟弱表示看题解看不懂……std看了几个小时大概看懂,还有一些细节的东西没有思考. 最难受的是题解和std好像并不是同一个人写的……数组状态不一样……看了好久才看出来f也是前缀和. F[i ...

  2. behavior planning——15.cost function design weightTweaking

    Designing cost functions is difficult and getting them all to cooperate to produce reasionable vehic ...

  3. Android ListView性能优化实例讲解

    前言: 对于ListView,大家绝对都不会陌生,只要是做过Android开发的人,哪有不用ListView的呢? 只要是用过ListView的人,哪有不关心对它性能优化的呢? 关于如何对ListVi ...

  4. Nginx 日志记录post数据,并使用goaccess进行日志分析

    nginx日志默认不会记录post数据 在nginx配置文件的http节 log_format 日志格式标识 [escape=json] 日志格式 比如:日志格式标识设置为main,添加escape= ...

  5. C#循环语句练习(三)

    for循环拥有两类:一.穷举:把所有可能的情况都走一遍,使用if条件筛选出来满足条件的情况. (1).羽毛球拍15元,球3元,水2元.200元每种至少一个,有多少可能. (2).百鸡百钱:公鸡2文钱一 ...

  6. 2019-1-29-win10-uwp-使用-Microsoft.Graph-发送邮件

    title author date CreateTime categories win10 uwp 使用 Microsoft.Graph 发送邮件 lindexi 2019-01-29 16:36:3 ...

  7. LuaForWindows_v5.1.4-45和lua-5.1.4.tar.gz

    Lua学习笔记(一) 安装调试环境 Lua学习笔记(一) 安装调试环境     觉得自己是该掌握一门脚本语言的时候了,虽然曾经用过C# 和JavaScript 写过Unity3D的脚本.但是,总觉得那 ...

  8. C# 操作XML学习笔记

    1. Customers.xml <?xml version="1.0" encoding="utf-8"?> <cust:customers ...

  9. Sphinx中文入门指南

    http://www.sphinxsearch.org/sphinx-tutorial 1.简介 1.1.Sphinx是什么 1.2.Sphinx的特性 1.3.Sphinx中文分词 2.安装配置实例 ...

  10. windows命令行下redis读取中文字符乱码

    我在eclipse上对redis进行了一个操作,添加了一个中文字符串进去,可以看到是添加成功了的 但是在命令行中读取的时候却成了乱码,如下图所示 这是因为windows命令行的编码是gbk 可以通过如 ...