FluentAPI深入
1. HasMaxLenght 设定字段得最大长度:
static void Main(string[] args)
{
using (TestDbContext ctx = new TestDbContext())
{ Person p = new Person
{
Name = "chenwwwwwwwwwwwwwwwwwwwwww",
Age=,
CreateDateTime=DateTime.Now
};
ctx.Persons.Add(p);
try
{
ctx.SaveChanges();
}
catch (DbEntityValidationException ex)
{
foreach (var e in ex.EntityValidationErrors)
{
foreach (var error in e.ValidationErrors)
{
Console.WriteLine(error.ErrorMessage);
}
} } Console.ReadKey();
}
}
依赖于数据库得“字段长度、是否为空”等约束是在数据提交到数据库服务器得时候才会检查‘EF得配置,则是由EF来检查得,如果检查出错根本不会被提交给服务器。
2. (有用)字段是否为空:
public PersonConfig()
{
this.ToTable("T_Persons");
this.Property(p=>p.Name).HasMaxLength();
this.Property(p => p.Name).IsRequired();//属性不能为空
this.Property(p => p.Name).IsOptional();//属性可以为空
}
默认规则是“主键属性不允许为空,引用类型允许为空”
public PersonConfig()
{
this.ToTable("T_Persons");
this.HasKey(p => p.Id); //主键
this.Property(p => p.Name).IsFixedLength(); //是否对应固定得长度
this.Property(p => p.Name).IsUnicode(false);//对应得数据库类型是varchar类型,而不是nvarchar
this.Property(p => p.Name).HasColumnName("Names"); //Name对应数据库中得字段名是Names
this.Ignore(p => p.Name);//某个字段不参与映射数据库
}
3、一对多
和关系映射相关得方法:
(1) 基本套路 this.Has****(p=>p.A).With****() 当前这个表和A属性表的关系是Has定义, With定义的是A对应的表和这个表的关系。
(2) HasOptional() 有一个是可选的(可以为空的); HasRequlred() 有一个是必须的(不能为空的); HasMany() 有很多的;
(3)WithOptional() 可选的; WithRequired() 必须的 ; WithMany() 很多的;
实例一:
public class Student
{
public long Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public long ClassId { get; set; }
public virtual Class Class { get; set; }
}
public class Class
{
public long Id { get; set; } public string Name { get; set; }
public int Count { get; set; } }
public class ClassConfig:EntityTypeConfiguration<Class>
{
public ClassConfig()
{
ToTable("T_Classes");
}
}
public class StudentConfig:EntityTypeConfiguration<Student>
{
public StudentConfig()
{
ToTable("T_Students");
}
}
Class c1 = new Class()
{
Name = "三年一班",
}; Student s1 = new Student()
{
Name = "chen",
Age = ,
Class = c1
}; ctx.Students.Add(s1);
ctx.SaveChanges();
实例二:
var s = ctx.Classes.First();
//双向设计,容易搞混
/*
foreach (var item in s.Students)
{
Console.WriteLine(item.Name);
}
*/
//数据库化思维,推荐用这种用法
foreach (var item in ctx.Students.Where(p => p.ClassId == s.Id))
{
Console.WriteLine(item.Name);
}
public class Class
{
public long Id { get; set; } public string Name { get; set; }
public int Count { get; set; }
public virtual ICollection<Student> Students { get; set; } = new List<Student>(); //这里就可以获得所有指向了当前对象的Student集合,不推荐这种双向设计关系 }
4、 多对多
public class Teacher
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Student> Students { get; set; } = new List<Student>(); } public class Student
{
public long Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public long? Class_Id { get; set; } public virtual Class Class { get; set; }
public virtual ICollection<Teacher> Teachers { get; set; } = new List<Teacher> (); }
public class StudentConfig:EntityTypeConfiguration<Student>
{
public StudentConfig()
{
ToTable("T_Students");
this.HasRequired(s => s.Class).WithMany().HasForeignKey(e => e.Class_Id);
}
} public class TeacherConfig:EntityTypeConfiguration<Teacher>
{
public TeacherConfig()
{
ToTable("T_Teachers");
this.HasMany(e => e.Students).WithMany(e=>e.Teachers).Map(e => e.ToTable("T_TeacherStudentRelations").MapLeftKey("teacherId").MapRightKey("studentId"));
}
}
static void Main(string[] args)
{
using (TestDbContext ctx = new TestDbContext())
{ Teacher t1 = new Teacher()
{
Name = "语文老师"
};
Teacher t2 = new Teacher()
{
Name = "数学老师"
}; Student s1 = new Student()
{
Name = "小李",
Age =
};
Student s2 = new Student()
{
Name = "小王",
Age =
};
Student s3 = new Student()
{
Name = "小章",
Age =
};
t1.Students.Add(s1);
t1.Students.Add(s2);
t2.Students.Add(s2);
t2.Students.Add(s3); ctx.Teachers.Add(t1);
ctx.Teachers.Add(t2); ctx.SaveChanges(); Console.ReadKey(); }
}
总结: (1)一对多中不建议配置一端的集合属性,因此配置的时候不用给WithMany()参数,如果配置了集合属性,则必须给WithMany参数;多对多关系必须要给WithMany参数
(2) 多对多移除关系:
static void Main(string[] args)
{
using (TestDbContext ctx = new TestDbContext())
{
var t=ctx.Teachers.Single(p=>p.Name=="数学老师");
var s = ctx.Students.Single(p => p.Name == "小章");
t.Students.Remove(s); ctx.SaveChanges(); Console.ReadKey(); }
}
(3)如果数据库创建好了再修改模型或者配置,运行就会报错,那么就要手动删除数据库或者
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<TestDbContext>());
(4)做项目时建议初期先把主要的类使用EF自动生成表,然后干掉Migration表,然后
Database.SetInitializer<TestDbContext>(null); //禁止DbMigration使用,手动修改实体类和数据库
5、延迟加载:
延迟加载(lazy load) ,只有用到关联的对象的数据,才会再去指向select查询,注意延迟加载只在关联对象属性上,普通属性没有这个东西;
注意启用延迟加载需要配置如下的两个属性(默认是true,因此不需要配置,只要别手动设置为false即可)
context.Configuration..ProxyCreationEnable=true; context.Configuration..LazyLoadingEnable=true;
分析延迟加载的原理:打印一下拿到的对象的GetType(),再打印一下GetType().BaseType;我们发现拿到的对象其实是Student子类的对象(如果结果不一致,说明类不是Public,没有关联的virtua属性l)
延迟加载的优点: 用到的时候才加载,没用到的时候不加载,避免了一次性加载所有的数据,提高了加载速度。缺点: 如果不用延迟加载,就可以一次数据库查询所有数据(join实现),用了延迟加载就要多次的执行数据库操作,提高了数据库服务器的压力
因此:如果关联的属性几乎都要读到,那么就不要用延迟加载;如果关联的属性只有较小的概率则可以启动延迟记载;
6、不延迟加载,怎样一次加载?
又想方便(必须是virtual)又想效率高!用EF永远都要把导航属性设置为virtual。
使用Include()方法:
(1)var s= ctx.Students.Include("Class").First(); //Include("Class")的意思是直接加载student的Class属性的数据。注意只有关联的对象属性才可以用Include,普通字段不可以;
(2) C#6.0 语法糖,可以使用nameof语法解决这个问题:
ctx.Students.Include(nameof(Student.Class)).First();
(3) //using System.Data.Entity; 推荐这种做法
ctx.Students.Include(e=>e.Class).First();
如果有多个属性需要一次性加载,也可以写多个Include:
(4)
using (TestDbContext ctx = new TestDbContext())
{
foreach (var s in ctx.Students)
{
Console.WriteLine(s.Name);
Console.WriteLine(s.Class.Name);
}
} //报错,多个DataReader一起执行了
三种解决方法:
在字符串上加上:MultipleActiveResultSets=true; 但是不支持其他数据库
执行一下Tolist() ,因为Tolist() 就遍历然后生成list:
using (TestDbContext ctx = new TestDbContext())
{
foreach (var s in ctx.Students.ToList())
{
Console.WriteLine(s.Name);
Console.WriteLine(s.Class.Name);
}
}
推荐做法:Include预先加载:
using (TestDbContext ctx = new TestDbContext())
{
foreach (var s in ctx.Students.Include(e=>e.Class))
{
Console.WriteLine(s.Name);
Console.WriteLine(s.Class.Name);
}
}
FluentAPI深入的更多相关文章
- EF CodeFirst系列(5)---FluentApi
FluentApi总结 1.FluentApi简介 EF中的FluentApi作用是通过配置领域类来覆盖默认的约定.在EF中,我们通过DbModelBuilder类来使用FluentApi,它的功能比 ...
- EF CodeFirst系列(7)---FluentApi配置存储过程
FluentApi配置存储过程 1.EF自动生成存储过程 EF6的CodeFirst开发模式支持给实体的CUD操作配置存储过程,当我们执行SaveChanges()方法时EF不在生成INSERT,UP ...
- EF CodeFirst系列(8)--- FluentApi配置单个实体
我们已经知道了在OnModelCreating()方法中可以通过FluentApi对所有的实体类进行配置,然而当实体类很多时,我们把所有的配置都放在OnModelCreating()方法中很难维护.E ...
- Entity Framework(三)---FluentAPI和增删查改
一.FluentAPI: 1.基本配置: namespace ConsoleApp14.ModelConfig { public class PersonConfig: EntityTypeConfi ...
- FluentAPI关系映射配置
都有哪几种关系? 1vs多,多vs多 1. 概念or关系映射相关方法: 1) 基本套路:this.Has***(o=>o.AAA).With***() 当前这个表和AAA属性的表关系是Has定义 ...
- FluentAPI配置
基本 EF 配置只要配置实体类和表.字段的对应关系.表间关联关系即可. 如何利用 EF的高级配置,达到更多效果:如果数据错误(比如字段不能为空.字符串超长等),会在 EF 层就会报错,而不会被提交给数 ...
- 用EFCore的 FluentAPI 方式生成MySql 带注释的数据库表结构
采用的是net Core 3.1框架下的 的WebAPI项目. 1. 创建ASP.NET Core Web项目 2. 添加NuGet引用包,包如下 Microsoft.EntityFramewor ...
- Entity Fremework以及Fluentapi学习
一.Entity Framework的入门 我这里采用的方式是数据库自己建立 然后模型类自己建立 数据库上下文类自己建立的方式 目的在于弄懂原理 其他的数据库优先等方式这里就不写了 教程有很多. ...
- 我画着图,FluentAPI 她自己就生成了
在 Newbe.ObjectVistor 0.3 版本中我们非常兴奋的引入了一个紧张刺激的新特性:使用状态图来生成任意给定的 FluentAPI 设计. 开篇摘要 在非常多优秀的框架中都存在一部分 F ...
- EF FluentAPI映射一对多 关系时候报错
提示很明显,不可为空的外键为空了,但是 问题是,我只是初始化 关系映射而已:见代码 public ColumnsCategoryMapConfiguration() { ToTable("C ...
随机推荐
- firewalld 使用简介
学习apache安装的时候需要打开80端口,由于centos 7版本以后默认使用firewalld后,网上关于iptables的设置方法已经不管用了,想着反正iptable也不会用,索性直接搬官方文档 ...
- 【LOJ6045】「雅礼集训 2017 Day8」价(网络流)
点此看题面 大致题意: 有\(n\)种药,每种药有一个权值,且使用了若干种药材.让你选择若干种药,使得药的数量与所使用的药材并集大小相等,求最小权值总和. 网络流 \(hl666\):这种数据范围,一 ...
- 【洛谷P1525】[NOIP2010]关押罪犯
关押罪犯 题目链接 思路: 二分图或并查集 这里讲并查集算法: 1.将每对罪犯的冲突关系按影响从大到小排序 2.将集合与(i+n)合并表示编号为i的罪犯不能在该集合内 3.依次从大到小处理冲突关系: ...
- 1.vue脚手架搭建项目
前言: 在使用Vue-cli脚手架搭建项目之前,需要安装node.js和npm以及vue-cli. 开始搭建项目: 1.打开cmd win+R 2.转到要搭建的项目路径: g: cd Webapp/v ...
- java乱码问题
我们知道JSP页面是需要转换为servlet的,在转换过程中肯定是要进行编码的.在JSP转换为servlet过程中下面一段代码起到至关重要的作用. <%@ page language=" ...
- 基于 win7下虚拟机的 GNSS-SDR安装过程
最近在安装 GNSS-SDR软件时,遇到了很多问题,这里回顾了我的安装过程,罗列了所遇到的问题和解决办法.希望后来者不要再踩这些坑了! 首先,在官方文档中看到,GNSS-SDR目前并不支持直接在 Wi ...
- Windows API窗口绘图程序设计
任务目标 设计一个简单的Windows 窗口程序,在程序窗口内任意位置按下鼠标左键,可绘制范围在10-100之间随机大小的正方形.并且显示的正方形用红色填充. 效果图 小结 程序先是触发鼠标左键点击事 ...
- Mysql_Binary_Install_Scripts(采用二进制方式安装)
1.1 MYSQL实现代码 #!/bin/bash ######################################## #auth:wolf_dreams #time:2018-1 ...
- 硬盘安装Windows Server 2008(解决系统盘符变成D盘)
硬盘安装Windows 2008系统方法 操作系统最好用的无疑是server 2003,但是现在Server 2003支持的软件越来越少,很多是故意不支持Server 2003了, 像php5.5以上 ...
- git重新下载项目
file-new-project from version control - git 修改网址为需要的网址