前言

EF已经发布很久了,也有越来越多的人在使用EF。如果你已经能够非常熟练的使用EF的功能,那么就不需要看了。本文意在将自己使用EF的方式记录下来备忘,也是为了给刚刚入门的同学一些指导。看完此文,你应该就学会以CodeFirst的方式操作数据库了。

本文主要内容

  • CodeFirst生成数据库的流程
  • 初始化配置
  • 数据库实体构造技巧
  • 主外键设置
  • decimal精度修改

项目框架搭建

本文所使用的开发工具是vs2015(EF6.1.3)

第一步:新建一个空白项目

第二步:引用EntityFramework

DbContext的初始化配置

DbContext作为操作数据库的网关,十分重要。我们需要对它进行一些类的初始化操作,例如:解决团队开发中,多人迁移数据库造成的修改覆盖问题。

代码如下:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace EFDemo.Core.EF
{
/// <summary>
/// EF访问数据库的接口
/// </summary>
public class MyDbContext : System.Data.Entity.DbContext
{
public MyDbContext()
: base("EFDemo")
{
//解决团队开发中,多人迁移数据库造成的修改覆盖问题。
Database.SetInitializer<MyDbContext>(null);
//base.Configuration.AutoDetectChangesEnabled = false;
////关闭EF6.x 默认自动生成null判断语句
//base.Configuration.UseDatabaseNullSemantics = true;
}
public MyDbContext(System.Data.Common.DbConnection oConnection)
: base(oConnection, true)
{
this.Configuration.LazyLoadingEnabled = true;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//表名不用复数形式
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
//移除一对多的级联删除约定,想要级联删除可以在 EntityTypeConfiguration<TEntity>的实现类中进行控制
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
//多对多启用级联删除约定,不想级联删除可以在删除前判断关联的数据进行拦截
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); base.OnModelCreating(modelBuilder);
}
//将实体对象写在这里,就可以生成对应的数据。 如下:
//public DbSet<Demo> Demo { get; set; } } }

项目位置:

Migrations下Configuration类的初始化配置

Configuration类的初始化配置十分重要,我们需要通过配置解决一系列迁移问题。例如:允许自动迁移,自动迁移默认情况下不扔掉列在我们的数据库中的表。如果我们不希望这样的行为,我们可以告诉迁移明确允许数据丢失的配置类的AutomaticMigrationDataLossAllowed属性设置为true。

代码如下:

namespace EFDemo.Core.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq; internal sealed class Configuration : DbMigrationsConfiguration<EFDemo.Core.EF.MyDbContext>
{
public Configuration()
{
//允许自动迁移
//不然会报错Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration.You can use the Add-Migration command to write the pending model changes to a code-based migration. //允许自动迁移
AutomaticMigrationsEnabled = true;
//自动迁移默认情况下不扔掉列在我们的数据库中的表。如果我们不希望这样的行为,我们可以告诉迁移明确允许数据丢失的配置类的AutomaticMigrationDataLossAllowed属性设置为true。
AutomaticMigrationDataLossAllowed = true;
} protected override void Seed(EF.MyDbContext 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. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
}

项目位置:

数据库对应实体对象的定义

CodeFirst模式需要我们先定义实体,然后通过实体生成数据。

通常我们设计数据库表时,每个表都有(ID,是否删除,备注,添加人,添加时间,修改人,修改时间)等字段。我们可以用基类处理

基类实体:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EFDemo.Core.Entity
{
public class BaseEntity
{ }
[Serializable]
public class BaseEntity<TKey> : BaseEntity
{
public BaseEntity()
{
this.AddTime = DateTime.Now;
} [Key]
[Display(Name = "编号")]
public TKey ID { get; set; }
[Display(Name = "排序")]
[Required(ErrorMessage = "{0}是必填项"), Range(, int.MaxValue, ErrorMessage = "{0}的范围是{1}到{2}")]
[DefaultValue()]
public int Sort { get; set; }
[Display(Name = "备注")]
[MaxLength(, ErrorMessage = "{0}最大长度{1}")]
public string Remark { get; set; }
[Display(Name = "是否删除")]
[Required]
public bool Deleted { get; set; }
public int AddUser { get; set; }
[Display(Name = "添加时间")]
[DisplayFormat(ApplyFormatInEditMode = true, ConvertEmptyStringToNull = true, DataFormatString = "{0:yyyy-MM-dd HH mm}", HtmlEncode = false, NullDisplayText = "数据无效")]
public DateTime AddTime { get; set; }
public int ModUser { get; set; }
[DisplayFormat(ApplyFormatInEditMode = true, ConvertEmptyStringToNull = true, DataFormatString = "{0:yyyy-MM-dd HH mm}", HtmlEncode = false, NullDisplayText = "数据无效")]
public DateTime? ModTime { get; set; } } }

省市区表:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EFDemo.Core.Entity
{
/// <summary>
/// 省市区
/// </summary>
public class Public_Area
{ [Key]
public Guid ID { get; set; } [Display(Name = "父亲ID")]
public Guid ParentID { get; set; } [Display(Name = "名称")]
[MaxLength(, ErrorMessage = "{0}最大长度{1}")]
public String Name { get; set; }
}
}

班级表:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EFDemo.Core.Entity
{
/// <summary>
/// 班级
/// </summary>
public class T_Classes : BaseEntity<int>
{
public T_Classes() {
this.T_Student = new List<Entity.T_Student>();
} [InverseProperty("T_Classes")]
public virtual List<T_Student> T_Student { get; set; } [Display(Name = "班级名称")]
[Required(ErrorMessage = "{0}是必填项")]
[MaxLength(, ErrorMessage = "{0}最大长度{1}")]
public string Name { get; set; } [Display(Name = "人数")]
public int Count { get; set; } [Display(Name = "班级经费")]
public decimal Money { get; set; }
}
}

学生表:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EFDemo.Core.Entity
{
/// <summary>
/// 学生
/// </summary>
public class T_Student : BaseEntity<int>
{ /// <summary>
/// 外键
/// </summary>
[ForeignKey("ClassesID")]
public virtual T_Classes T_Classes { get; set; }
[Display(Name = "班级ID")]
public int ClassesID { get; set; } [Display(Name = "姓名")]
[Required(ErrorMessage = "{0}是必填项")]
[MaxLength(, ErrorMessage = "{0}最大长度{1}")]
public string Name { get; set; } [Display(Name = "性别")]
public bool Sex { get; set; } [Display(Name = "年龄")]
public int Age { get; set; } [Display(Name = "电话")]
[Required(ErrorMessage = "{0}是必填项")]
[RegularExpression(@"^(13[0-9]|15[0-9]|18[0-9])\d{8}$", ErrorMessage = "不是手机号格式")]
[MaxLength(, ErrorMessage = "{0}最大长度{1}")]
public string Phone { get; set; } /// <summary>
/// 省市县外键
/// </summary> [ForeignKey("ProvinceID")]
public virtual Public_Area Public_Area_Province { get; set; }
[Display(Name = "省ID")]
public Guid ProvinceID { get; set; } [ForeignKey("CityID")]
public virtual Public_Area Public_Area_City { get; set; }
[Display(Name = "市ID")]
public Guid CityID { get; set; } [ForeignKey("CountyID")]
public virtual Public_Area Public_Area_County { get; set; }
[Display(Name = "县ID")]
public Guid CountyID { get; set; }
}
}

班级表和学生表是一对多的关系,省市区表和学生表是一对多的关系,同时学生表中有多个省市区表的外键。

项目位置:

使用命令生成数据库

第一步:将实体对象加入到DbContext中,

如下:

//将实体对象写在这里,就可以生成对应的数据。 如下:
//public DbSet<Demo> Demo { get; set; } public DbSet<Public_Area> Public_Area { get; set; }
public DbSet<T_Classes> T_Classes { get; set; }
public DbSet<T_Student> T_Student { get; set; }

第二步:在EFDemo.Core项目下的App.config文件夹中添加生成数据库的配置项

配置文件代码如下:

name="EFDemo"中的EFDemo要和DbContex中的一致。 
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<!--生成数据库的连接字符串-->
<add name="EFDemo" connectionString="Data Source=.;Initial Catalog=EFDemoDB;User ID=sa;Password=123456;MultipleActiveResultSets=True;Application Name=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>

第三步:执行更新命令

启动项目一定要选择EFDemo.Core

生成数据库如下:

主外键关系设置

班级和学生一对多关系的设置:

一个表中的多个外键是另一个表中的主键的情况:学生表和省市县表

生成的数据库如下:

需要注意的是:这种情况,在Public_Area表中不能反向设置 public virtual List<T_Student> T_Student ,不然会报错。

decimal怎么保存四位小数  

decimal默认保留两位小数,我们需要通过如下设置让其保留四位小数。

在DbContext中配置班级表中的Money字段让其保留四位小数:

执行Update-Database命令:

结果如下:

使用EF操作数据库数据

第一步:

让EFDemo.Web应用EFDemo.Core程序集。

第二步:

配置EFDemo.Web中的webconfig中的数据库连接字符串:

 <connectionStrings>
<!--操作数据库的连接字符串-->
<add name="EFDemo" connectionString="Data Source=.;Initial Catalog=EFDemoDB;User ID=sa;Password=123456;MultipleActiveResultSets=True;Application Name=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>

第三步:

使用EF向数据库添加数据

    public ActionResult Index()
{
using (var db = new Core.EF.MyDbContext())
{
Public_Area area1 = new Public_Area()
{
ID = Guid.NewGuid(),
Name = "河南",
ParentID = Guid.NewGuid() };
db.Public_Area.Add(area1);
Public_Area area2 = new Public_Area()
{
ID = Guid.NewGuid(),
Name = "郑州",
ParentID = area1.ID };
db.Public_Area.Add(area2);
Public_Area area3 = new Public_Area()
{
ID = Guid.NewGuid(),
Name = "新郑",
ParentID = area2.ID };
db.Public_Area.Add(area3); //添加测试数据
T_Classes classes = new T_Classes()
{
Name = "高中三班",
Money =
};
db.T_Classes.Add(classes);
T_Student student = new T_Student()
{
ClassesID = classes.ID,
Name = "张三",
Phone = "",
Sex = true,
ProvinceID = area1.ID,
CityID = area2.ID,
CountyID = area3.ID,
};
db.T_Student.Add(student);
db.SaveChanges();
}
return View();
}

第四步:

查看数据库数据

Demo完整代码下载

EFDemo.Core.7z

下一篇:EF查询之性能优化技巧

EF使用CodeFirst方式生成数据库&技巧经验的更多相关文章

  1. 2.EF中 Code-First 方式的数据库迁移

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/code-first-migrations-with-entity-framework/ 系列目 ...

  2. EF中 Code-First 方式的数据库迁移

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/code-first-migrations-with-entity-framework/ 系列目 ...

  3. 学习EF之CodeFirst二(数据库对应映射)

    在上一篇文章我们简单通过一个实例完成对CodeFirst的理解,我们通过实体生成数据库里的表和字段,虽然有一些默认的配置生成规定,但其实我们可以能过对实体进一步控制从而对生成的表字段进行更加符合我们要 ...

  4. EntityFramework系列:SQLite.CodeFirst自动生成数据库

    http://www.cnblogs.com/easygame/p/4447457.html 在Code First模式下使用SQLite一直存在不能自动生成数据库的问题,使用SQL Server C ...

  5. ASP.NET MVC5利用EF,反向自动生成数据库

    1.在Model类里面,写好相应的属性. using System; using System.Collections.Generic; using System.Linq; using System ...

  6. 【EF6学习笔记】(一)Code First 方式生成数据库及初始化数据库实际操作

    本篇参考原文地址: Creating an Entity Framework Data Model 说明:学习笔记参考原文中的流程,为了增加实际操作性,并能够深入理解,部分地方根据实际情况做了一些调整 ...

  7. EF6 学习笔记(一):Code First 方式生成数据库及初始化数据库实际操作

    EF6 学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本篇参考原文地址: Creating an Entity Framework Data Model 说明:学习 ...

  8. .Net Core建站(2):EF Core+CodeFirst数据库迁移

    上一篇的话,说了下怎么使用EF7 实现 CodeFirst去生成数据库, 其实还有好多问题的,这次一点一点的解决吧,都挺简单,不过零零散散的,, 1.读取配置文件,获得链接字符串 2.使用数据库进行增 ...

  9. 第十七节: EF的CodeFirst模式的四种初始化策略和通过Migration进行数据的迁移

    一. 四种初始化策略 EF的CodeFirst模式下数据库的初始化有四种策略: 1. CreateDatabaseIfNotExists:EF的默认策略,数据库不存在,生成数据库:一旦model发生变 ...

随机推荐

  1. 5.JAVA之GUI编程窗体事件

    我们回顾下第三篇时的内容: 在3.JAVA之GUI编程Frame窗口中窗体是无法直接关闭的,想要关闭须进程管理器结束进程方式关掉. 现在我们就来解决下这个问题. ******************* ...

  2. 关于 WP 开发中.xaml 与.xaml.cs 的关系

    今天我们先来看一下在WP8.1开发中最长见到的几个文件之间的关系.比较论证,在看这个问题之前我们简单看看.NET平台其他两个不同的框架: Windows Forms 先看看Window Forms中的 ...

  3. 实例讲解react+react-router+redux

    前言 总括: 本文采用react+redux+react-router+less+es6+webpack,以实现一个简易备忘录(todolist)为例尽可能全面的讲述使用react全家桶实现一个完整应 ...

  4. react-native的tabbar和navigator混合使用

    前段时间搭建项目使用了navigator和react-native-tab-navigator,现在我教大家搭建一个通用的简单框架. 先把几张图贴在这里,这就是我们今天要搭建的东西,别看页面简单,但是 ...

  5. 1、Python基本概念

    1.数 python中有4种类型的数--整数.长整数.浮点数和复数 2.字符串 单引号.双引号或者三引号包含的字符序列,如: 'char' #单引号 "char" #双引号 ''' ...

  6. Atitit.ide技术原理与实践attilax总结

    Atitit.ide技术原理与实践attilax总结 1.1. 语法着色1 1.2. 智能提示1 1.3. 类成员outline..func list1 1.4. 类型推导(type inferenc ...

  7. Workflow笔记2——状态机工作流

    状态机工作流 在上一节Workflow笔记1——工作流介绍中,介绍的是流程图工作流,后来微软又推出了状态机工作流,它比流程图功能更加强大. 状态机工作流:就是将工作流系统中的所有的工作节点都可以看做成 ...

  8. Maven对插件进行全局设置

    并不是所有插件都适合从命令行配置,有些参数的值从项目创建到发布都不会改变,或者很少改变,对于这种情况,在POM文件中一次性配置就显然比重复在命令行中输入要方便了. 用户可以在生命插件的时候,对插件进行 ...

  9. spring springMVC

    spring是一个开源框架,是为了解决企业应用程序开发,功能如下 目的:解决企业应用开发的复杂性 功能:使用基本的javabean代替EJB,并提供了更多的企业应用功能 范围:任何java应用 总之: ...

  10. git&&github使用方法总结

    vn / git作用:在多人协作开发过程中,我们使用git负责项目源代码的版本管理,所有的开发人员操作的是同一个仓库中的源码 1.创建一个远程的仓库(在gitHub上) 2.创建一个本地的仓库 新建文 ...