博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EntityFramework 详解
阅读量:3518 次
发布时间:2019-05-20

本文共 12745 字,大约阅读时间需要 42 分钟。


第07章 EntityFramework

1.感慨

     昨天递交了辞职书(5月前走人),心里不是滋味。很快Boss特地赶来单位约见我(我也是醉了!一年多来,见到他真是屈指可数),我有一种受宠若惊的感觉。

     可我知道这是一种错觉!虽然我做程序员不到两年,但出来讨饭也有10年了。人生经历,生活阅历,多少有一些自己的观点,感悟。

     就当是人之将走,面子挽留吧!这会做人的,都会这样,这么说,给老板一个赞吧!

     这看人吧,如果你胸怀宽广,看坏人也是好人,不会歧视;如果你心胸狭窄,看谁对你好,就认为他好,而对你不好的,一定看作是坏人。

     就受雇于人而言,对任何雇佣之人的看法,我如今都是认为应该心态放好点,人家是我的衣食父母,有什么不顺心的事,也要适应,当受不了,也就是要离开的时候了。

     不管怎样,我感谢老板,感谢公司,感谢同事……!虽奉献不多,但索取物质也不多,能力倒是提高了,算是度过一段宝贵的时光,谈不上是光辉岁月也罢!

2.说明

     关于EF知识已经发了两个短篇,对帖子的质量我很惭愧。凭着几篇文章不可能面面俱到,何况我水平也非常有限。

3.EF6

3.1初步目录及说明

     下面是用VS2013开发环境创建的项目:

    

     说明:控制台项目类型,安装EF版本为6.1.3, 数据库连接字符串配置:     

      EFContext.cs代码:

复制代码
using Consoles.EF6.Models;using System.Data.Entity;namespace Consoles.EF6.Repositories{    public class EFContext : DbContext    {        public EFContext() : base("DefaultConnection") { }        public DbSet
Categories { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity
().HasKey(k => k.CategoryId) //设置主键 .Property(q => q.CategoryName).IsRequired();//设置不能为空 } }}
复制代码

       注:

          a.数据库上下文构造方法,继承基类,其参数是DefaultConnection,配置的数据库连接字符串中name值要一致;

             如果name值和上下文类名(EFContext)一致的话,上下文类的构造方法也可以省略.

          b.为了保持实体类"干净",不使用DataAnnotations数据注解特性,改为Fluent API配置方式.当然有些已经默认了,我们照样进行配置.

             如:属性为Id(字母不分大小写)或为类名+Id,它会默认为主键,但我们也配置:Entity<Category>().HasKey(k => k.CategoryId)

             疑问:这种两种方式,到底采用那种好呢?这个……我表示无语,你自个看那个爽啦。

3.2示例一

      Category.cs代码:

复制代码
namespace Consoles.EF6.Models{    public class Category    {        public int CategoryId { get; set; }        public string CategoryName { get; set; }        public string Description { get; set; }    }}
复制代码

      Program.cs代码:

复制代码
using Consoles.EF6.Models;using Consoles.EF6.Repositories;using System;using System.Collections.Generic;using System.Linq;using System.Data.Entity.Migrations;namespace Consoles.EF6{    class Program    {        static void Main(string[] args)        {            #region 示例一            using (var db = new EFContext())            {                var categories = new List
{ new Category(){ CategoryName="Mobile",Description="手机大类"}, new Category(){ CategoryName="Computer",Description="电脑大类"} }; //AddOrUpdate:根据指定列,相同就更新,不相同就添加 categories.ForEach(list => db.Categories.AddOrUpdate(c => c.CategoryId, list)); db.SaveChanges(); //var query = db.Categories; var query = from c in db.Categories select c; //遍历输出 foreach (var item in query) { Console.WriteLine("类别:{0};说明:{1}", item.CategoryName, item.Description); } } #endregion Console.ReadKey(); } }}
复制代码

       运行结果:

      

       查看数据库:

      

3.3示例二

      我们添一个Subcategory.cs,其代码:

复制代码
namespace Consoles.EF6.Models{    public class Subcategory    {        public int SubcategoryId { get; set; }        public string SubcategoryName { get; set; }        public int CategoryId { get; set; }        public Category Category { get; set; }    }}
复制代码

      再修改Category.cs代码:

复制代码
using System.Collections.Generic;namespace Consoles.EF6.Models{    public class Category    {        public int CategoryId { get; set; }        public string CategoryName { get; set; }        public string Description { get; set; }        public ICollection
Subcategories { get; set; } }}
复制代码

      设计关系为:大类Category:子类Subcategory=1:N。子类必须属于某一个大类,也就是外键不能为空。配置Fluent API     

复制代码
using Consoles.EF6.Models;using System.Data.Entity;namespace Consoles.EF6.Repositories{    public class EFContext : DbContext    {        public EFContext() : base("DefaultConnection") { }        public DbSet
Categories { get; set; } public DbSet
Subcategories { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity
().HasMany(s => s.Subcategories) .WithRequired(c => c.Category).HasForeignKey(f=>f.CategoryId); modelBuilder.Entity
().HasKey(k => k.CategoryId); modelBuilder.Entity
().Property(p => p.CategoryName).HasMaxLength(20); modelBuilder.Entity
().HasKey(K => K.SubcategoryId); modelBuilder.Entity
().Property(p => p.SubcategoryName).IsRequired(); } }}
复制代码

       Program.cs代码:

复制代码
using Consoles.EF6.Models;using Consoles.EF6.Repositories;using System;using System.Collections.Generic;using System.Linq;using System.Data.Entity.Migrations;namespace Consoles.EF6{    class Program    {        static void Main(string[] args)        {            #region 示例二            using (var db = new EFContext())            {                var categories = new List
{ new Category(){ CategoryName="Mobile",Description="手机大类"}, new Category(){ CategoryName="Computer",Description="电脑大类"} }; categories.ForEach(list => db.Categories.AddOrUpdate(c => c.CategoryId, list)); db.SaveChanges(); var subcategories = new List
{ new Subcategory(){ SubcategoryName="2G",Category=db.Categories.Single(c=>c.CategoryName=="Mobile")}, new Subcategory(){ SubcategoryName="3G",Category=db.Categories.Single(c=>c.CategoryName=="Mobile")}, new Subcategory(){ SubcategoryName="4G",Category=db.Categories.Single(c=>c.CategoryName=="Mobile")}, new Subcategory(){ SubcategoryName="Desktop",Category=db.Categories.Single(c=>c.CategoryName=="Computer")}, new Subcategory(){ SubcategoryName="Tablet ",Category=db.Categories.Single(c=>c.CategoryName=="Computer")} }; subcategories.ForEach(list => db.Subcategories.AddOrUpdate(c => c.SubcategoryId, list)); db.SaveChanges(); var query = from c in db.Categories select c; foreach (var item in query) { Console.WriteLine("类别:{0};说明:{1}", item.CategoryName, item.Description); } } #endregion Console.ReadKey(); } }}
复制代码

        查看数据库:

        

        嘎嘎! 一对多关系OK!Subcategories表的外键也不为空!

3.4示例三

        我们再添加一个Product.cs,其代码:

复制代码
using System.Collections.Generic;namespace Consoles.EF6.Models{    public class Product    {        public int ProductId { get; set; }        public string ProductName { get; set; }        public ICollection
Subcategories { get; set; } }}
复制代码

      再修改Subcategory.cs: 

复制代码
using System.Collections.Generic;namespace Consoles.EF6.Models{    public class Subcategory    {        public int SubcategoryId { get; set; }        public string SubcategoryName { get; set; }        public int CategoryId { get; set; }        public Category Category { get; set; }        public ICollection
Products { get; set; } }}
复制代码

     修改EFContext.cs:

复制代码
using Consoles.EF6.Models;using System.Data.Entity;namespace Consoles.EF6.Repositories{    public class EFContext : DbContext    {        public EFContext() : base("DefaultConnection") { }        public DbSet
Categories { get; set; } public DbSet
Subcategories { get; set; } public DbSet
Products { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity
().HasMany(s => s.Subcategories) .WithRequired(c => c.Category).HasForeignKey(f => f.CategoryId); modelBuilder.Entity
().HasKey(k => k.CategoryId); modelBuilder.Entity
().Property(p => p.CategoryName).HasMaxLength(20); modelBuilder.Entity
().HasKey(K => K.SubcategoryId); modelBuilder.Entity
().Property(p => p.SubcategoryName).IsRequired(); modelBuilder.Entity
().HasKey(k => k.ProductId); modelBuilder.Entity
().Property(p => p.ProductName).HasMaxLength(120); modelBuilder.Entity
() .HasMany(c => c.Products).WithMany(p => p.Subcategories) .Map(t => t.MapLeftKey("SubCategoryId") .MapRightKey("ProductId") .ToTable("SubcategoryProduct")); } }}
复制代码

        查看数据库:

       

3.5初始化数据

        前面我们是在Main方法写的模拟数据代码,是不是不太好?在“第05章”文中,我也说过有预留的问题,在这补充一下。

        添加SampleData.cs,其代码:

复制代码
using Consoles.EF6.Models;using System.Collections.Generic;using System.Data.Entity;using System.Linq;using System.Data.Entity.Migrations;namespace Consoles.EF6.Repositories{    public class SampleData : DropCreateDatabaseIfModelChanges
{ protected override void Seed(EFContext db) { var categories = new List
{ new Category(){ CategoryName="Mobile",Description="手机大类"}, new Category(){ CategoryName="Computer",Description="电脑大类"} }; categories.ForEach(list => db.Categories.AddOrUpdate(c => c.CategoryId, list)); db.SaveChanges(); var subcategories = new List
{ new Subcategory(){ SubcategoryName="2G",Category=db.Categories.Single(c=>c.CategoryName=="Mobile")}, new Subcategory(){ SubcategoryName="3G",Category=db.Categories.Single(c=>c.CategoryName=="Mobile")}, new Subcategory(){ SubcategoryName="4G",Category=db.Categories.Single(c=>c.CategoryName=="Mobile")}, new Subcategory(){ SubcategoryName="Desktop",Category=db.Categories.Single(c=>c.CategoryName=="Computer")}, new Subcategory(){ SubcategoryName="Tablet ",Category=db.Categories.Single(c=>c.CategoryName=="Computer")} }; subcategories.ForEach(list => db.Subcategories.AddOrUpdate(c => c.SubcategoryId, list)); db.SaveChanges(); } }}
复制代码

     注:关于多对多关系的数据添加,参加"第05章"示例!   

     添加配置节点:

    

         这样只要有访问数据库时,就会初始化数据了,如:  

复制代码
using Consoles.EF6.Models;using Consoles.EF6.Repositories;using System;using System.Collections.Generic;using System.Linq;using System.Data.Entity.Migrations;namespace Consoles.EF6{    class Program    {        static void Main(string[] args)        {            using (var db = new EFContext())            {                var query = from c in db.Categories select c;                foreach (var item in query)                {                    Console.WriteLine("类别:{0};说明:{1}", item.CategoryName, item.Description);                }            }            Console.ReadKey();        }    }}
复制代码

         我们并没在程序显式的代码中执行SampleData里的Seed方法,通过配置文件即可(在不需要时,也可以disableDatabaseInitialization关闭).

4.EF7

4.1目录及说明

    下面是用VS2015开发环境创建的项目:

    

    说明:ASP.NET 5版的WebApi项目类型;

    依赖和Commands配置:

   

    commands之ef是迁移用的,这在“第06章”已经介绍过,这里会略过。  

4.2示例

    由于EF7暂时不直接支持多对多实体关系(也可能我了解有限),所以这里举例一对多。

    Category.cs代码: 

复制代码
using System.Collections.Generic;namespace WebApies.EF7.Models{    public class Category    {        public int CategoryId { get; set; }        public string CategoryName { get; set; }        public string Description { get; set; }        public ICollection
Subcategories { get; set; } }}
复制代码

     Subcategory.cs代码:

复制代码
namespace WebApies.EF7.Models{    public class Subcategory    {        public int SubcategoryId { get; set; }        public string SubcategoryName { get; set; }        public int CategoryId { get; set; }        public Category Category { get; set; }    }}
复制代码

     EFContext.cs代码:

复制代码
using Microsoft.Data.Entity;using WebApies.EF7.Models;using Microsoft.Data.Entity.Metadata;namespace WebApies.EF7.Repositories{    public class EFContext : DbContext    {        public DbSet
Categories { get; set; } public DbSet
Subcategories { get; set; } protected override void OnConfiguring(DbContextOptions options) { options.UseSqlServer( "Server=(localdb)\\mssqllocaldb;Database=TestDB;Trusted_Connection=True;MultipleActiveResultSets=true"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity
().HasMany(C => C.Subcategories).WithOne().ForeignKey(f=>f.CategoryId); modelBuilder.Entity
().Key(k => k.CategoryId); modelBuilder.Entity
().Property(p => p.CategoryName).MaxLength(20); modelBuilder.Entity
().Key(K => K.SubcategoryId); modelBuilder.Entity
().Property(p => p.SubcategoryName).Required(); } }}
复制代码

        迁移完毕后,查看数据库:

       

        注:MaxLength没有起作用!(完整版的sqlserver是正常的)

        基架模板代码创建:

          

        此时目录:

       

        这是T4模板代码,这个MVC版的,webapi版本的还得等等了!

5.小结

       本章算是对前两篇补充,关于EF篇就不再介绍了。

       预告: 下一章介绍依赖注入,这个在ASP.NET 5又是给力的!然后进入完整的项目实战了。    

转载地址:http://jcaqj.baihongyu.com/

你可能感兴趣的文章
java中解决String equals相同但===不同的问题
查看>>
Java new一个对象的过程
查看>>
程序员代码面试指南之窗口最大值数组
查看>>
selenium之 chromedriver与chrome版本映射表
查看>>
小白解决:‘chromedriver‘ executable needs to be in PATH的问题(亲测有效)
查看>>
Cannot find class [org.apache.commons.dbcp.BasicDataSource(亲测有效)
查看>>
小白学习[leetcode]之402移掉k位数字
查看>>
DNN和RNN和DNN之间的区别
查看>>
小白学习[leetcode]之215数组中的第K个最大元素
查看>>
Java 将PDF 转为Word、图片、SVG、XPS、Html、PDF/A(亲测有效)
查看>>
小白学习之程序员代码面试指南之单调栈结构
查看>>
小白之java虚拟机工作学习面试准备(持续更新)
查看>>
小白学习[leetcode]之455分发饼干 (贪心算法)
查看>>
小白学习[leetcode]之135分发糖果 (贪心算法)
查看>>
小白读论文之. Show and Tell Lessons learned from the 2015 MSCOCO Image Captioning Challenge
查看>>
小白学习[leetcode]之435无重叠区间(贪心算法)
查看>>
java二维数组使用lambda表达式进行排序
查看>>
java图解从编译到运行(详细)
查看>>
为什么java的局部变量要初始化而全局变量不用
查看>>
校园一卡通的实现机制(图解)
查看>>