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 ...
随机推荐
- andriod给ListView中的TextView增加跑马灯效果
正常情况下跑马灯效果只需要在TextView中添加android:ellipsize="marquee" android:singleLine="true" a ...
- HttpServletRequest request 获取form参数的两种方式
@RequestMapping(value="/pay",method = RequestMethod.POST) public String buildRequest(HttpS ...
- ajaxfileup.js
<img id="tinyPic" class="user-icon" :src="headPortrait"><inpu ...
- JavaScript 十行原生代码实现复制内容到剪贴板
十行原生代码,不引入任何 JS 库,目前大部分浏览器与移动平台都可兼容. function copyToClipboard(value, callback) { var textarea = docu ...
- Python 初始—(字符编码解码)
字符编码之间的编码转换则需要通过Unicode 进行转换,那么需要一个编码和解码实现与Unicode进行关联转换 例如utf-8转gbk utf-8----decode----->Unicode ...
- centos7部署harbor
官网 https://github.com/goharbor/harbor 1.升级系统内核 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrep ...
- VMware运行时“内部错误”的解决方法
解决方法:打开虚拟机实体目录,如下:发现有两个虚拟机配置文件,一个文件大小为4KB,另一个为空.现在虚拟机默认使用为空的配置文件了. 将大小为空的虚拟机配置文件删除掉,然后将另一个配置文件重名命. 接 ...
- java @override 全部报错
问.java @override 全部报错 答: 错误:在 eclipse 的新工作空间开发项目时,出现大面积方法编译错误.鼠标放在方法名上后显示让我们去掉 @override 注解 原因: @Ove ...
- SQL_server_2008_r2和visual studio 2010旗舰版的安装(2013-01-16-bd 写的日志迁移
(以下操作是在Oracle VM virtualBox虚拟机中操作的,其实VMware Workstation 9虚拟机也挺不错的,不过用了很久的vmware想换个虚拟机用用 就暂时用Oracle V ...
- JZOJ 3534. 【NOIP2013提高组day1】货车运输
Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的 ...