EFCodeFirst学习笔记
EF_Code_First:数据查询
EF Code First:数据查询EF的CodeFirst是个好东西,让我们完全不用考虑数据库端(注意,这里并不是说不需要对数据库知识进行了解),一切工作都可以通过代码来完成。
EF是ORM,已经把数据访问操作封装得很好了,可以直接在业务层中使用,那我们为什么还要对其进行那么多封装呢?在我看来,封装至少能带来如下的好处。
一、前言首先对大家表示抱歉,这个系列已经将近一个月没有更新了,相信大家等本篇更新都等得快失望了。
实在没办法,由于本人水平有限,写篇博客基本上要大半天的时间,最近实在是抽不出这么长段的空闲时间来写。
另外也是一直没想好本篇应该怎样写比较容易理解,于是就一天一天的拖着了。
废话不多说,言归正传。
EF的CodeFirst是个好东西,让我们完全不用考虑数据库端(注意,这里并不是说不需要对数据库知识进行了解),一切工作都可以通过代码来完成。
EF是ORM,已经把数据访问操作封装得很好了,可以直接在业务层中使用,那我们为什么还要对其进行那么多封装呢?在我看来,封装至少能带来如下的好处:1.把EF的相关对象封装在数据访问层中,解除了业务层对EF的依赖。
2.统一EF的数据操作,以保证业务层使用相同的代码规范3.隐藏EF的敏感配置,降低EF的使用难度这里就引入一个问题,应该怎样来进行EF的封装呢,既要保证使用的统一与方便性,又要保持EF的灵便性,否则,封装将变成给业务层设置障碍。
下面,主要针对数据查询进对可能出现的误用情况进行分析。
二、查询问题分析(一) 数据查询应该在哪做在EF中,面向对象的数据查询主要提供了两种方式:1.TEntity DbSet<TEntity>.Find(params object[] keyValues):针对主键设计的通过主键查找单个实体,会先在EF的本地数据集Local中进行查询,如果没有,再去数据库中查询。
2.IQueryable<T>、IEnumerable<T>类型的所有数据查询的扩展方法(由于DbSet<T>继承于IQueryable<T>与IEnumerable<T>),如SingleOrDefault,FirstOrDefault,Where等。
C#EF使用(CodeFirst模式)
C#EF使⽤(CodeFirst模式)⼀、EF的简单介绍,EF是⼀种通过映射操作实现数据交互的ORM框架技术⼆、简单使⽤1、安装EntityFrameWork(通过⼯具-NeGet程序包管理-管理NeGet程序包来安装或者添加引⽤)*最终的⽬的是为了在项⽬上添加进这两个dll注:如果是使⽤了web API,要在API层引⼊这两个dll安装完会在app.config或者web.config⽣成此配置信息2.配置数据库连接字符串,如果⽤了web Api同样要在api层的webconfig中配置连接字符串注:连接字符串可通过在桌⾯建.udl⽂件来获取3.开始写想要⽣成的数据库表对应的模型类(需要添加ponentModel.DataAnnotations这个引⽤,此引⽤可添加模型组件特性的注释如:主键、字符长度、表名字、列名字、以及是否映射到数据库等)--如果是有主外键关系的表则在模型中:(或给它加特性)public int 外键表(实体类)id名字{get;set;}public 外键表(实体类)id名字外键表(实体类)id名字s{get;set;}4.写上下⽂类5.开始初始化数据库(记得把上下⽂类所在的类库设置为启动项或者在程序包控制台的默认项⽬中选择此类库)在程序包管理控制台中输⼊:get-help EntityFrameWork*2.通过命令,开始迁移:Enable-Migrations --命令是申请开始迁移的,Add-Migration --是添加迁移:需要给它取个名字,如: Add-Migration InitUpdate-Database --这个是在数据库⽣成表的语句每次执⾏都会在项⽬中和SQL Server 中⽣成迁移⽂件:接下来就可以使⽤EF语句进⾏操作了。
ef code first 表中文注释
ef code first 表中文注释1. 主键(Primary Key):主键是用于唯一标识一条记录的字段或字段组合。
在 EF Code First 中,可以使用 "[Key]" 注释来标识主键。
主键可以是单个字段,也可以是多个字段的组合。
使用主键可以提高数据的查询效率,并且可以保证数据的唯一性。
2. 外键(Foreign Key):外键用于关联两个表之间的关系。
在 EF Code First 中,可以使用 "[ForeignKey]" 注释来标识外键。
外键通常是一个与其他表的主键相关联的字段。
通过使用外键,可以在两个表之间建立关系,并且可以实现数据的引用和一致性。
3. 非空(Not Null):非空用于限制字段的值不能为空。
在 EF Code First 中,可以使用 "[Required]" 注释来标识非空字段。
非空字段可以确保数据的完整性和有效性,避免了数据的丢失和错误。
4. 唯一(Unique):唯一用于限制字段的值不能重复。
在 EF Code First 中,可以使用 "[Index(IsUnique = true)]" 注释来标识唯一字段。
唯一字段可以确保数据的唯一性,避免了重复数据的插入和查询。
5. 长度(Length):长度用于限制字段值的最大长度。
在 EF Code First 中,可以使用 "[MaxLength]" 注释来标识字段的最大长度。
长度可以用于限制字符串字段的长度,避免了数据的溢出和错误。
6. 默认值(Default Value):默认值用于指定字段在插入数据时的默认值。
在 EF Code First 中,可以使用 "[DefaultValue]" 注释来标识字段的默认值。
默认值可以用于设置字段的默认数值或默认字符串,避免了数据插入时的繁琐操作。
EF框架step by step(7)—Code First DataAnnotations(1)
EF框架step by step(7)—Code First DataAnnotations(1)2011-05-12 08:37 by 杨延成, 4204 阅读, 25评论, 收藏, 编辑Data annotation特性是在.NET 3.5中引进的,给 web应用中的类提供了一种添加验证的方式。
Code First允许你使用代码来建立实体框架模型,同时允许用Data annotation特性来配置类和属性的某些特性。
其实在前面的几篇文章中,有用到几个,在这一篇里,进行一次比较全面的介绍KeyEF框架要求每个实体必须有主键字段,他需要根据这个主键字段跟踪实体。
CodeFirst方法在创建实体时,也必须指定主键字段,默认情况下属性被命名为ID、id或者[ClassName]Id,将映射为数据表中的主键如果没有类似的命名,并且也未显示指明主键,则生成失败,引发异常。
如果想要自定义主键列名,则可以使用Key注释[Key] public int MyId { get; set; }Required当要求数据库在字段,不能为空时[Required]public string BookTitle { get; set; }MaxLength 、MinLength设置数据库字段的长度范围[MaxLength(10),MinLength(6)] public string Password { get; set; }NotMapped当创建数据表时,用此属性修饰的属性,不会被创建为数据表字段[NotMapped] public int MyProperty { get; set; }ComplexTypeComplex属性是将一个对象做为另一个对象的属性。
映射到数据库中则子对象表现为多个属性字段。
具体可参考:EF框架step by step(6)—处理实体complex属性[ComplexType] public class Publisher { public string PublisherName { get; set; } public string PublisherAddress { get; set; } } ConcurrencyCheck并发检查允许你标识一个或者多个属性在实体更新时,要进行检查是否与原实体一致。
sqlite ef codefirst 事务操作
sqlite ef codefirst 事务操作SQLite是一种轻量级的嵌入式关系型数据库管理系统,具有高性能、低内存占用和跨平台等优点。
Entity Framework (EF)是一种ORM(object-relational mapping)框架,它是.NET Framework的一部分,可以非常方便地对数据库进行增删改查等操作,同时支持多种数据库,包括SQLite。
在使用EF进行SQLite开发的过程中,事务操作是非常重要的一部分,可以保证数据的完整性和一致性。
本文将介绍SQLite EF CodeFirst事务操作的具体内容。
1.事务操作概述事务是指一系列操作组成的逻辑单元,这些操作要么都执行成功,要么都不执行。
如果其中有任何一个操作失败,则整个事务都会被回滚。
事务可以保证数据的完整性和一致性,可以避免数据出现不一致的情况。
在SQLite EF CodeFirst中,可以通过DbContext 来创建事务。
2.事务的创建和提交在SQLite EF CodeFirst中,可以通过以下代码创建一个事务:using (var transaction = db.Database.BeginTransaction()) { /* Transaction operations here */ }在这个示例中,使用DbContext的Database属性创建一个事务,使用BeginTransaction方法开始一个事务,并将其赋值给transaction对象。
在事务中,可以执行一系列操作,包括插入、修改和删除等操作。
在操作完成后,可以使用以下代码提交事务:mit();在这个示例中,使用Commit方法提交事务,如果事务中所有的操作都执行成功,则所有的操作都会被提交。
3.事务的回滚如果在事务中出现了错误,可以使用以下代码回滚事务:4.事务的嵌套在SQLite EF CodeFirst中,可以嵌套多个事务。
EF——一个实体对应两张表,两个实体对应一张表06(转)
EF——⼀个实体对应两张表,两个实体对应⼀张表06(转)本篇⽇记我们将详细探讨如何将表现领域的类映射到现有的数据库。
现在的经济形势不是太好,很多公司都取消了开发新系统的预算。
在这种情况下,通常的做法是把原有的⼏个系统修改⼀下做个集成,先凑合⽤着得了。
如果要对原有的系统做功能提升的话,肯定要重⽤原来的数据库结构并做⼀些⼩的改进,在这种情况下我们怎样使⽤Code First 呢?我们可以按照原有系统的业务逻辑和CR(Change Request)中的新业务逻辑建⽴domain中的类,然后使⽤Fluent API把这些类映射到原有数据库的表中,或修改原有系统的数据结构。
我相信通过前⼏篇的⽇记,⼤家已经知道了怎样去⾃定义各个⽅⾯的数据库映射了。
这种⽅法虽然给我们机会重新审视我们的业务逻辑,但是原有系统中许多没有变化的部分也需要按照Code First的⽅法重头创建类并映射到原有的数据表,给我们的开发带来了很多不必要的⼯作量。
为了提⾼我们的开发效率,减少在使⽤Code First升级系统时不必要的⼯作量,微软发明了Entity Framework Power Tools. 这个⼯具可以使⽤反向⼯程,在原有数据库的基础上⽣成Code First中使⽤的纯粹代表domain的类和数据库映射配置。
博客园上有很多关于这个⼯具的介绍,⼤家可以上博客园搜索。
这个⼯具虽然很好,但是他只能帮你减少你的⼯作量,不可能完全替代你的⼯作。
⽐如说原来的数据库中有⼀个表,你经过对业务逻辑的分析,发现表中的字段应该属于两个类,但是你还不能改变现有的数据库结构,这种情况需要你⾃⼰配置数据库映射来搞定。
或者原来数据库中的两个表,在你的新的业务逻辑中属于同⼀个类,也给根据特定的业务逻辑进⾏数据库映射的配置。
所以我今天主要介绍如何解决以上的两个问题。
1.在不修改数据库结构的前提下,如何将两个类映射到同⼀个数据库表。
2.在不修改数据库结构的前提下,如何将⼀个类映射到两个数据库表。
EFCodeFirst系列(2)---CodeFirst的数据库初始化
EFCodeFirst系列(2)---CodeFirst的数据库初始化1. CodeFirst的默认约定1.领域类和数据库架构的映射约定 在介绍数据库的初始化之前我们需要先了解领域类和数据库之间映射的⼀些约定。
在CodeFirst模式中,约定指的是根据领域类(如Student,Grade类)⾃动配置概念模型的⼀些默认规则。
在上⼀节的⼩栗⼦中,我们没有在领域类中做任何配置,但是EF API帮我们配置了主外键、关系、列的数据类型等,这就是约定在起作⽤。
下表中列除了⼀些默认的CodeFirst约定:默认规则描述Schema EF创建所有的DB对象都放在dbo架构中。
dbo.StudentsTable Name实体名的复数,如Student->StudentsForeign key 默认情况,EF会找和主实体的主键名⼀样名字的列如果没有的话EF创建⼀个导航属性名_导航属性主键形式的外键,如:在dbo.Students表中,外键是Grade_GradeId列顺序EF创建的数据库列的数据和领域类属性的顺序⼀致,唯⼀可能不⼀致的是会把主键放在第⼀位映射(mapping)默认EF会把领域类的所有属性都映射到数据库,可以通过[NotMapped]实现领域类/属性的不映射级联删除默认启⽤所有的类型关系下表显⽰了C#数据类型到SqlServer数据类型的映射:bool bitbyte tinyintshort smallintint intlong bigintfloat realdouble floatdecimal decimal(18,2)string nvrchar(Max)datetime datetimebyte[]varbinary(Max)下图显⽰了领域类和数据库架构的映射:2.⼀些补充当我们使⽤导航属性时,EF6中把1对多关系作为默认关系。
注意:EF6中不包含1对1,多对多的默认关系,我们需要⾃⼰通过Fluent API或者注释属性进⾏配置。
转:EF调用存储过程、函数
转:EF调⽤存储过程、函数⼀.ef4.1 codeFirst 修改表结构增加字段等 EF code first需要重新⽣成库导致数据丢失的问题说这个问题前⾸先先说下我使⽤ef4.1 codefirst的⽬的. 是因为可以有更纯净的POCO 不再有EDMX这些东西⽽不是真正的⽤ code first 先有代码再⽣成数据库.所以我虽然使⽤的是codefirst 但是本质依然是数据库优先.所以这个被问的很多的问题解决办法其实是⾮常简单的.只要你的数据库已经存在了那么即使你⽤code first ef 也不会给你去⽣成数据库的.这个时候你增加表字段甚⾄增加表只要把实体类也相应的修改则数据库⾥的数据是不会被清空的.说下我的开发步骤先设计数据库并建⽴数据库=>通过EF⼯具⽣成映射和实体类=>开发代码当遇到修改时=> 先修改数据库如添加字段或表等=>再修改实体类=>继续开发这样就不会有重新⽣成数据的烦恼了⽽且项⽬⾥也不会出现edmx~还有使⽤EF4.3 的数据迁移功能也可以完美解决~⼆.ef4.1 没有了edmx等复杂的东西变得简单⼲净但如何使⽤存储过程,存储过程可以返回表可以返回数值也有可能是执⾏修改删除增加等该怎么做?说这个问题前依然先说下我的观点.个⼈认为既然使⽤orm框架就应该把业务逻辑等都放到业务逻辑层⽽不应该再使⽤存储过程。
我更偏重重业务逻辑层轻存储过程这样的开发~再ef4.0⾥添加存储过程⽐较容易有edmx 调⼀调存储过程就添加上了但是在ef4.1⾥只有⼲净的poco 不再有edmx了改怎么办呢?尤其是存储过程可以是查表查值或者执⾏修改删除.⼀个⼀个来解决1.执⾏返回表类型的存储过程先上存储过程随⼿写的⼀个最简单的Create PROCEDURE [dbo].[ProSelectStu]@StudentID intASBEGINSelect Student.* from Enrollment,Studentwhere Enrollment.StudentID=Student.StudentID and Enrollment.StudentID=@StudentIDENDGO执⾏存储过程的⽅法是⽤直接执⾏sql的⽅式我在我的⽂章第九篇有过详细的介绍~⼤家可以先去看下执⾏表的存储过程其实是⾮常强⼤的延迟加载等都有体现博客园的陆⽼师已经写了写的⾮常清楚了~我这⾥就不再写了⼤家可以去他那看下提供个连接~2.执⾏返回值的存储过程先上存储过程CREATE PROCEDURE [dbo].[ProSelectCount]@StuId intASBEGINselect COUNT(*) from Enrollment where StudentID=@StuIdEND⼀个简单的查询数量这⾥⽤sqlQuery 执⾏访问数据库因为需要提供返回类型⽽我们返回的是int 所以先得到int的类型3.执⾏增删改CREATE PROCEDURE [dbo].[ProDel]@stuId int,@courseId intASBEGINDELETE FROM [WLFSchool].[dbo].[Enrollment]where StudentID=@stuId and CourseID=@courseIdEND这个⽤的是操作数据库返回受影响⾏数三.ef4.1 如何使⽤数据库视图?每个视图都要去建⽴对应的实体类么?有简单的⽅法么?先说下最传统的⽅法只需把视图当成表建⽴对应的实体类然后加到dbcontext ⾥即可。
EFCodefirst多对多关系操作中间表的增删改查(CRUD)
EFCodefirst多对多关系操作中间表的增删改查(CRUD)前⾔此⽂章只是为了给新⼿程序员,和经验不多的程序员,在学习ef和lambada表达式的过程中可能遇到的问题。
本次使⽤订单表和员⼯表建⽴多对多关系。
⾸先是订单表:public class Order{public int OrderId { get; set; }public string OrderTitle { get; set; }public string CustomerName { get; set; }public DateTime TransactionDate { get; set; }[ConcurrencyCheck][Timestamp]public byte[] TimeStamp { get; set; }public virtual ICollection<Employee> InvolvedEmployees { get; set; }}接下来是员⼯表:public class Employee{public int EmployeeId { get; set; }public string EmployeeName { get; set; }public virtual ICollection<Order> Orders { get; set; }}映射⽂件(mapping):public class OrderMap:EntityTypeConfiguration<Order>{public OrderMap(){this.HasKey(o => o.OrderId);//OrderId为⾃增长this.Property(o => o.OrderId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);this.Property(o => o.OrderTitle).IsRequired().HasMaxLength(64);//订单名称为必填,最⼤长度为64;this.Property(o => o.CustomerName).IsRequired().HasMaxLength(64);//订单名称为必填,最⼤长度为64;this.Property(o => o.TransactionDate).IsRequired(); //订单名称为必填,最⼤长度为64;}}public class EmployeeMap:EntityTypeConfiguration<Employee>{///<summary>///构造函数///</summary>public EmployeeMap(){this.HasKey(x => x.EmployeeId);this.ToTable("Employees");this.Property(x => x.EmployeeName).IsRequired().HasMaxLength(20);//设置多对多的关系 .Map()配置⽤于存储关系的外键列和表。
EF6学习笔记一:code-first简单创建数据库、表的一些过程
EF6学习笔记⼀:code-first简单创建数据库、表的⼀些过程我的EF学习笔记是按照汪鹏(⽹名Jeffcky)⼤侠《你必须掌握的Entity Framework 6.x与Core 2.0》来弄的。
这也是我第⼀篇博客,感觉这东西不能乱写啊,算了,⼲吧。
EF我之前是做过的,但是只是⼀些零碎的东西,不成系统。
EF是什么呢?ORM框架object renational mapping 对象关系映射,下⾯我就⽤⾃⼰的话来了。
数据库⾥⾯存放数据⽤表,⽽我们程序代码使⽤类,⼀个是数据世界的弄法,⼀个是对象世界的弄法。
EF就是为我们做这种对象映射的处理,让我可以不⽤关⼼数据库,只关系类怎么设计就⾏了。
我说完了。
它主要就是这个对吧,当然会有其他的很多东西,通过程序直接创建数据库,然后更多的精⼒放到了类上,业务逻辑上,突然多出来的精⼒没处使,是不是就弄出了什么领域驱动设计?现在来创建⼀个控制台程序,安装EF,打开程序包管理控制台输⼊命令:install-package entityframework创建Blog类,写⼀个EFDbContext类,这个类派⽣⾃DbContext,为blog公开⼀个DbSet属性然后在main⽅法⾥⾯实例化上下⽂对象,添加⼀个blog实例,接着查询这个实例,打印出来然后控制台⼤概过了⼗多秒,看到了刚刚添加的数据,那么简单的创建数据库、表就完了~namespace _20190105{public class Blog{public int ID { get; set; }public string Name { get; set; }public string Url { get; set; }public DateTime? CreatedTime { get; set; }public double Double { get; set; }public float Float { get; set; }}}namespace _20190105{// 此上下⽂是与数据库交互的⼀个中间桥梁,可以称之为会话,为每⼀个模型公开⼀个DbSet<>,定义DbSet有三种⽅式public class EFDbContext:DbContext{// DbSet 三种设计⽅式,不太懂,我随便弄了⼀种//public DbSet<Blog> Blog { get; set; }//public IDbSet<Blog> Blog { get; set; }public DbSet<Blog> Blog {get { return Set<Blog>(); }}}}namespace _20190105{class Program{static void Main(string[] args){// 上下⽂实例化,添加⼀个blog实例using (EFDbContext db = new EFDbContext()){db.Blog.Add(new Blog{CreatedTime = DateTime.Now,Double = 11.11,Float = 2.2f,ID = 1,Name = "第er篇博客",Url = "http://localhost:8080"});db.SaveChanges();Console.WriteLine(JsonConvert.SerializeObject(db.Blog.ToList()));}}}}来看看数据库,对照着模型看⼀下,数据库和表是什么样⼦的。
EFCodeFirst下,当实体结构发生修改怎么更新数据库结构【常用总结】
EFCodeFirst下,当实体结构发⽣修改怎么更新数据库结构【常⽤总结】⽅法1:由于.NetCore 没有实体⽣成模型,所有数据库结构改变后,程序中升级数据库便不能向FarmWork程序⼀样更新数据模型。
可在 VS 中,打开【⼯具】-【NuGet 包管理器】-【程序包管理器控制台】菜单项,随后就能打开控制台窗⼝。
输⼊以下命令Scaffold-DbContext "Server=.;Database=数据库名称;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Force -UseDatabaseNames即可。
此语句会覆盖之前⽣成数据。
⽅法2:使⽤dotnet ef命令创建Migrations:dotnet ef migrations add [NAME]修改Blog类,添加⼀个字段 public string NewField { get; set; },在命令⾏执⾏命令dotnet ef migrations add NewField,然后运⾏程序,可以看到数据库已经更新,__EFMigrationsHistory表也多了⼀条对应的记录⽅法2:(命令要⼤写)我们只需在Configuration类的构造函数⾥⾯插⼊⼀句:AutomaticMigrationDataLossAllowed = true;就⾏了。
然后在程序包管理控制台输⼊命令:Add-Migration initUpdate-Database init 就完成了这种修改,当然,很多情况下运⾏updata-database修改会报错,如果报错我们可以强制运⾏,只需加上⼀个参数-force,完整命令:Update-Database -Force注意:sqlite微型数据库删除表中的⼀个字段不⽀持,报错如下SQLite does not support this migration operation ('DropColumnOperation'). For more information, see /fwlink/?LinkId=723262sqlite微型数据库删除表中的⼀个字段不⽀持,报错如下解决办法:由于项⽬需求变更,我需要在sqlite的表中删除⼀个字段,通⽤的sql操作语句如下:alter table task drop column custom_fields;结果数据库提⽰如下错误:sqlite> ALTER TABLE task DROP COLUMN custom_fields;Error: near "DROP": syntax error搜索得知,原来SQLite⽬前还不⽀持drop column,所以必须想出另外⼀种⽅法来进⾏表字段的删除。
efcore codefirst 生成表名字规则-概述说明以及解释
efcore codefirst 生成表名字规则-概述说明以及解释1.引言1.1 概述EFCore CodeFirst是Entity Framework Core框架中的一种数据库访问模式,它通过使用代码来定义实体类型和数据库模式之间的映射关系,从而向数据库中生成表结构。
在EFCore CodeFirst中,生成表名字的规则是非常重要的,因为它决定了数据库中每个实体对应的表的名称。
在EFCore CodeFirst中,默认的表名字生成规则是将实体类型的名称转换为数据库表的名称。
如果实体类型的名称是单数形式,那么生成的表名字也是单数形式;如果实体类型的名称是复数形式,那么生成的表名字也是复数形式。
例如,如果有一个实体类型叫做"Product",则生成的表名字将为"Products"。
然而,有时我们可能需要自定义表名字的生成规则以满足特定的需求。
EFCore CodeFirst提供了一些选项来配置表名字的生成方式。
我们可以通过在实体类型上使用数据注解、使用Fluent API或使用数据库上下文的配置来指定表名字的生成规则。
在接下来的文章中,我们将详细探讨EFCore CodeFirst的表名字生成规则,并介绍如何使用不同的方法配置表名字的生成方式,以满足各种需求。
通过深入了解表名字生成规则,读者将能够更好地掌握EFCore CodeFirst的使用方法,并能够灵活地应对不同的数据库设计需求。
1.2 文章结构文章结构部分的内容可以包含以下内容:文章结构是指文章的整体组织架构和内容安排。
一个良好的文章结构可以帮助读者更好地理解和阅读文章。
下面是本文的结构:2. 文章结构在本节中,将介绍本文的整体结构和各章节的内容安排。
本文共分为三个主要部分,分别是引言、正文和结论。
2.1 引言引言部分是本文的开篇部分,旨在引起读者的兴趣并引入本文的主题。
在引言部分,将包括以下内容:- 概述:对EFCore CodeFirst以及生成表名字规则的简要介绍,为读者提供背景信息。
EFCodeFirst数据注解特性详解
EFCodeFirst数据注解特性详解数据注解特性是.NET特性,可以在EF或者EF Core中,应⽤于实体类上或者属性上,以重写默认的约定规则。
在EF 6和EF Core中,数据注解特性包含在ponentModel.DataAnnotations命名空间和ponentModel.DataAnnotations.Schema命名空间下。
这些特性不仅仅适⽤于EF,同样适⽤于 MVC以及数据控件。
ponentModel.DataAnnotations.Schema Attributes[Table(string name,[Schema = string])]name 想要定义的表名称Schema 可选参数,数据库的模式名称[Column(string name,[Order = int],[TypeName = string])]name 列名Order 可选参数,列的顺序,从0开始,注意必须为每个属性都设置(不可重复)才能⽣效、TypeName 可选参数,列的数据类型[NotMapped] 不将该属性映射到数据库的列[ForeignKey(string name)] 设置外键3种⽅式[Index(string name)] 为列创建索引IsClustered⽤来创建聚合索引, IsUnique⽤来创建唯⼀索引。
[InverseProperty(string name)] 有多个对应关系时,指定关系ponentModel.DataAnnotations Attributes [Key] 设为主键(EF Core中不能使⽤)[Required] 设置列不为空[MaxLength(int)] 设置最⼤长度,只能⽤在string类型和byte[]数组类型。
EFCodeFirst学习笔记:表映射多个Entity到一张表和一个Entity到多张表
EFCodeFirst学习笔记:表映射多个Entity到⼀张表和⼀个Entity到多张表多个实体映射到⼀张表Code First允许将多个实体映射到同⼀张表上,实体必须遵循如下规则:实体必须是⼀对⼀关系实体必须共享⼀个公共键观察下⾯两个实体:public class Person{[Key]public int PersonId { get; set; }public int SocialSecurityNumber { get; set; }public string FirstName { get; set; }public string LastName { get; set; }[Timestamp]public byte[] RowVersion { get; set; }public PersonPhoto Photo { get; set; }}public class PersonPhoto{[Key, ForeignKey("PhotoOf")]public int PersonId { get; set; }public byte[] Photo { get; set; }public string Caption { get; set; }public Person PhotoOf { get; set; }}它们之间是⼀对⼀的关系,并且主键数据类型相同,所以我们可以将它们映射到同数据库的同⼀个表中,只需指定表名即可:[Table("People")]public class Person[Table("People")]public class PersonPhotoPS:我按照上⾯的模型映射,但⽣成数据库的时候会报错:实体类型“PersonPhoto”和“Person”⽆法共享表“People”,因为它们不在同⼀类型层次结构中,或者它们之间的匹配的主键没有有效的⼀对⼀外键关系。
EF使用CodeFirst方式生成数据库技巧经验
EF使⽤CodeFirst⽅式⽣成数据库技巧经验前⾔EF已经发布很久了,也有越来越多的⼈在使⽤EF。
如果你已经能够⾮常熟练的使⽤EF的功能,那么就不需要看了。
本⽂意在将⾃⼰使⽤EF的⽅式记录下来备忘,也是为了给刚刚⼊门的同学⼀些指导。
看完此⽂,你应该就学会以CodeFirst的⽅式操作数据库了。
本⽂主要内容CodeFirst⽣成数据库的流程初始化配置数据库实体构造技巧主外键设置decimal精度修改项⽬框架搭建本⽂所使⽤的开发⼯具是vs2015(EF6.1.3)第⼀步:新建⼀个空⽩项⽬第⼆步:引⽤EntityFrameworkDbContext的初始化配置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判断语句//eDatabaseNullSemantics = true;}public MyDbContext(mon.DbConnection oConnection): base(oConnection, true){zyLoadingEnabled = true;}protected override void OnModelCreating(DbModelBuilder modelBuilder){//表名不⽤复数形式modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();//移除⼀对多的级联删除约定,想要级联删除可以在 EntityTypeConfiguration<TEntity>的实现类中进⾏控制modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();//多对多启⽤级联删除约定,不想级联删除可以在删除前判断关联的数据进⾏拦截modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();base.OnModelCreating(modelBuilder);}//将实体对象写在这⾥,就可以⽣成对应的数据。
EF架构~CodeFirst生产环境的Migrations
EF架构~CodeFirst⽣产环境的MigrationsMigrations即迁移,它是EF的code first模式出现的产物,它意思是说,将代码的变化反映到数据库上,这种反映有两种环境,⼀是本地开发环境,别⼀种是服务器的⽣产环境,本地开发环境主要使⽤包管理⼯具的update-database即可完成数据库的迁移(变更),⽽在⽣产环境就显得⿇烦⼀些,因为你不会在⽣产环境放程序源代码和VS开发⼯具,哈哈.服务器上⽣产环境的数据迁移如果我们有迁移⽂件如下{/// <summary>/// 要在升级过程中执⾏的操作。
/// </summary>public override void Up(){DropForeignKey("dbo.WebDataSettings", "WebDataCtrlId", "dbo.WebDataCtrls");DropForeignKey("dbo.WebDataSettings", "DepartmentId", "dbo.WebDepartments");RenameColumn(table: "dbo.WebDataSettings", name: "DepartmentId", newName: "WebDepartmentsId");RenameIndex(table: "dbo.WebDataSettings", name: "IX_DepartmentId", newName: "IX_WebDepartmentsId");AddForeignKey("dbo.WebDataSettings", "WebDataCtrlId", "dbo.WebDataCtrls", "ID", cascadeDelete: true);AddForeignKey("dbo.WebDataSettings", "WebDepartmentsId", "dbo.WebDepartments", "ID", cascadeDelete: true);}/// <summary>/// 要在降级过程中执⾏的操作。
EF下ModelFirst、CodeFirst、DataBaseFirst利与弊
EF下ModelFirst、CodeFirst、DataBaseFirst利与弊通过项⽬,我们了解到EF框架有三种数据持久化的⽅式,也就是标题中我所提到的三种。
那么这些⽅式之间⼜有什么联系和区别呢?篇幅原因,本篇博客不再分别介绍每种⽅法如何实现的了,⼤家⽤的时候可以去Sou~⼀下。
先分别介绍⼀下这三种⽅法的联系:1.Database First是基于已存在的数据库,利⽤某些⼯具(如VS提供的EF设计器)创建实体类,数据库对象与实体类的匹配关系等,你也可以⼿动修改这些⾃动⽣成的代码及匹配⽂件。
也就是从⼀个数据库开始,然后⽣成实体框架和相应代码。
2.Model First 是先利⽤某些⼯具(如VS的EF设计器)设计出可视化的实体数据模型及他们之间的关系,然后再根据这些实体、关系去⽣成数据库对象及相关代码⽂件。
3.Code First 这种⽅式需要先写⼀些代码,如实体对象,数据关系等,然后根据已有的代码描述,⾃动创建数据对象。
但其实这种⽅法与Model First是⾮常类似的。
我们⾃⼰写的代码,其实就是⽤代码表⽰实体模型,⽽Model First是⽤可视化的⽅式描述了实体模型。
下⾯分析这三种⽅式的优缺点:Database-First模式明显性能会差点,但是它很适合初学者,或者是⽐较急的⼩型项⽬。
还有⼀点,我们在做项⽬时可能不容易体会到它的好处,但如果做数据库结构⽐较成熟稳定的产品时,我们可以很轻松的使⽤数据库⽣成实体模型,从⽽实现快速开发。
Model-First模式优点是开发⼈员能够在模型设计完成后,可以利⽤VS等⼯具快速⽣成数据库脚本。
缺点是设计模型时完全了解数据库的结构,在模型中⼿动添加表关系,并且⽣成的脚本有点不简洁。
Code-First模式优点是性能⽐较好,且代码较少冗余。
不过它的缺点也有很多,由于都是代码编写的,⽐如更新数据库。
这三种⽅式各有利弊,使⽤过程中我们要按实际需求来选择。
这些⼯具的出现和使⽤,⼤⼤提⾼了开发⼈员的开发速度,使得数据库、模型等出现了复⽤、扩展的可能,在应对变化⽅⾯也做了⾜够的⼯作。
EF使用Code
EF使⽤Code First模式给实体类添加复合主键using System;using System.Collections.Generic;using ponentModel.DataAnnotations;using ponentModel.DataAnnotations.Schema;using System.Linq;using System.Web;namespace MyFirstMvcApp.Models{/// <summary>/// 登录记录/// </summary>public class LoginRecordInfo{/// <summary>/// 登录的邮件地址(主键)/// </summary>[Key,Column(Order=1)]public string Email { get; set; }/// <summary>/// 登录的客户端IP/// </summary>public string LoginHostIP { get; set; }/// <summary>/// 登录的客户端主机名/// </summary>public string LoginHostName { get; set; }/// <summary>/// 登录时间(主键)/// </summary>[Key,Column(Order=2)]public DateTime LoginTime { get; set; }}}使⽤特性Key和Column设置复合主键,Key表⽰字段是主键,Order⽤来设置主键的顺序。
使⽤Key和Column需要添加命名空间:Key的命名空间:ponentModel.DataAnnotations;Column的命名空间:ponentModel.DataAnnotations.Schema;到此这篇关于EF使⽤Code First模式给实体类添加复合主键的⽂章就介绍到这了。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
EF Code First 学习笔记:约定配置要更改EF中的默认配置有两个方法,一个是用Data Annotations(在命名空间ponentModel.DataAnnotations;),直接作用于类的属性上面;还有一个就是Fluent API,通过新增相应的配置类来覆盖默认配置。
现在我们用这两个来对比了解EF中的约定配置。
主键:KEYData Annotations:通过Key关键字来标识一个主键[Key]public int DestinationId { get; set; }Fluent API:public class BreakAwayContext : DbContext{public DbSet<Destination> Destinations { get; set; }public DbSet<Lodging> Lodgings { get; set; }protected override void OnModelCreating(DbModelBuilder modelBuilder){//Fluent APImodelBuilder.Entity<Destination>().HasKey(d => d.DestinationId);base.OnModelCreating(modelBuilder);}}外键Data Annotations:public int DestinationId { get; set; }[ForeignKey("DestinationId")]public Destination Destination { get; set; }注意,指定列名存在,如上面的DestinationId,则类中必须存在名称为DestinationId的属性。
Fluent API:modelBuilder.Entity<Lodging>().HasRequired(p =>p.Destination).WithMany(p=>p.Lodgings).HasForeignKey(p => p.DestinationId);长度Data Annotations:通过StringLength(长度),MinLength(最小长度),MaxLength(最大长度)来设置数据库中字段的长度。
[MinLength(10),MaxLength(30)]public string Name { get; set; }[StringLength(30)]public string Country { get; set; }Fluent API:没有设置最小长度这个方法。
modelBuilder.Entity<Destination>().Property(p => ).HasMaxLength(30);modelBuilder.Entity<Destination>().Property(p =>p.Country).HasMaxLength(30);非空Data Annotations:用Required来标识,还可以设置是否可允许空字符串,显示错误消息等。
[Required]public string Country { get; set; }[Required(ErrorMessage="请输入描述")]public string Description { get; set; }Fluent API:modelBuilder.Entity<Destination>().Property(p => p.Country).IsRequired();数据类型Data Annotations:TypeName//将string映射成ntext,默认为nvarchar(max)[Column(TypeName = "ntext")]public string Owner { get; set; }Fluent API:modelBuilder.Entity<Lodging>().Property(p => p.Owner).HasColumnType("ntext"); 表名Data Annotations:Table[Table("MyLodging")]public class Lodging{public int LodgingId { get; set; }public string Name { get; set; }public string Owner { get; set; }public decimal Price { get; set; }public bool IsResort { get; set; }public Destination Destination { get; set; }}Fluent API:modelBuilder.Entity<Lodging>().ToTable("MyLodging");列名Data Annotations:Column[Column("MyName")]public string Name { get; set; }Fluent API:modelBuilder.Entity<Lodging>().Property(p =>).HasColumnName("MyName");自增长如果主键是int类型,EF为默认设置为增长。
但如果是GUID类型,则要显示的设置自增长。
Data Annotations:DatabaseGeneratedpublic class Person{[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]public Guid SocialId { get; set; }public string FirstName { get; set; }public string LastName { get; set; }}看看创建数据的脚本,会加一句ALTER TABLE[dbo].[People]ADD DEFAULT (newid()) FOR[SocialId]Fluent API:modelBuilder.Entity<Person>().Property(p =>p.SocialId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);忽略列映射类中有些属性,特别是一些通过计算或合并列得出的结果,我们并不需要其记录到数据库中,就可以通过配置不让它生成在数据库中。
Data Annotations:NotMapped[NotMapped]public string Name{get{return FirstName + "" + LastName;}}Fluent API:NotMappedmodelBuilder.Entity<Person>().Ignore(p => );忽略表映射对于不需要映射到数据库中的表,我们也可以取消其映射。
Data Annotations:[NotMapped]public class Person{[Key]public Guid SocialId { get; set; }public string FirstName { get; set; }public string LastName { get; set; }}Fluent API:modelBuilder.Ignore<Person>();时间戳时间戳只对数据类型为byte[]的属性有效,并且一个类中只能有一个设置为时间戳的属性。
Data Annotations:Timestamp[Timestamp]public Byte[] TimeStamp { get; set; }Fluent API:modelBuilder.Entity<Lodging>().Property(p => p.TimeStamp).IsRowVersion();复杂类型Data Annotations:ComplexType[ComplexType]public class Address{public string Country { get; set; }public string City { get; set; }}Fluent API:plexType<Address>();Entity Framework 复杂类型为了说明什么是复杂属性,先举一个例子。
public class CompanyAddress{public int ID { get; set; }public string CompanyName { get; set; }public string StreetAddress { get; set; }public string City { get; set; }public string State { get; set; }public string ZipCode { get; set; }}public class FamilyAddress{public int ID { get; set; }public string StreetAddress { get; set; }public string City { get; set; }public string State { get; set; }public string ZipCode { get; set; }}上面有两个类:公司地址和家庭地址,它们有四个相同的属性:StreetAddress、City、State、ZipCode。
映射到数据库中的结构如图:这里,我们可以将这四个属性集合成一个复杂属性Address,修改后的类为:public class CompanyAddress{public int ID { get; set; }public string CompanyName { get; set; }public Address Address { get; set; }}public class FamilyAddress{public int ID { get; set; }public Address Address { get; set; }}[ComplexType]public class Address{public string StreetAddress { get; set; }public string City { get; set; }public string State { get; set; }public string ZipCode { get; set; }}此时,所生成的数据库如图:可以看到,两张表中仍然具有相应的地址属性信息。