- 从实体到数据,使用T4模板生成
- 数据到实体,使用上下文(context)交互(继承DBcontext)
- EF实体框架有3种类型,Data First、Model First、Code First
using(context con = new context())){ Model modelName= new Model{ 对象属性 = 值 ...... } db.Model.Add(名称);//提交到内存 db.SaveChanges();//提交到数据库 return modelName.Key; }
注:如果数据库ID主键为自增,可以在EF添加后直接读取modelName.Key主键值,EF会根据自增自动回写主键值。 2.2 查询(Select) 2.21 语义:使用linq查询,返回集合。 #简单查询单个值
using(context con = new context())){ return con.Model.Where(linq表达式).FirstOrDefault(); }
#简单查询多个值
using(context con = new context())){ return con.Model.Where(linq表达式).FirstOrDefault(); }
#直接查询到DTO对象
using(context con = new context())){ return con.Model.Where(linq表达式).Select(q=>new DTOModel(){ dtoModelField1 = q.Field1, dtoModelField2 = q.Field2, ...... })FirstOrDefault(); }
#使用let进行子查询
using(context con = new context())){ return con.Model.Where(linq表达式).Select(q=>new DTOModel(){ dtoModelField1 = q.Field1, dtoModelField2 = q.Field2, ...... })FirstOrDefault(); var result = from modelName1 in con.Model1 let modelItemList = from modelName2 in con.Model2 where modelName2.foreignKey == modelName1.key select new DTO.DTO_ModelItem() { key = modelName2.BlogMeid, field = modelName2.fieldName, ...... } select new DTO_Model() { key = modelName1.BlogMeid, field = modelName1.fieldName, item = modelItemList.Tolist() }; return result.ToList(); }
#使用Join进行内连接查询
sing(context con = new context())){ var result = from modelName1 in con.Model1 join modelName2 in con.Model2 on modelName1.foreignKey equals modelName2.key select new DTO_Model() { key = modelName1.BlogMeid, field1 = modelName1.fieldName1, filed2 = modelName2.fieldName1, ...... }; }
#使用Join + into 进行左外连接查询
using(context con = new context())){ var result = from modelName1 in con.Model1 join modelName2 in con.Model2 on modelName1.foreignKey equals modelName2.key into modelName3 from modelName4 in modelName3.DefaultIfEmpty() select new DTO_Model() { key = modelName1.BlogMeid, field1 = modelName1.fieldName1, filed2 = modelName4.fieldName1, ...... }; }
注:DefaultIfEmpty操作符能够为实序列提供一个默认的元素,如果不使用default关键字,需要在其当空时指定默认对象值。
modelName3.DefaultIfEmpty(new Model2(){ key = "defaultfieldValue", field1 = "defaultfieldValue", }}))
2.22 如果数据仅用于查询,而不会在后续更新删除,可以使用AsNoTracking() 直接修改EF模型状态,以减少跟踪对象状态改变而导致的性能损耗。
using(context con = new context())){ db.Model.AsNoTracking().Where(user=>user.field=='fieldValue').ToList(); }
2.3 更新(Update) 1.查询数据后修改
using(context con = new context())){ var Model = con.Model.Where(linq表达式).FirstOrDefault(); Model.field="fieldValue"; con.SaveChanges(); }
2.已知ID对象修改 1.查询数据后修改
1.查询数据后修改 using(context con = new context())){ Model modelName = new Model(){ id=1, field = "fieldValue" }; //Attach:将给定实体以System.Data.EntityState.Unchanged状态附加到上下文中 con.Attach(modelName); /或者 con.Entry(modelName).State = Microsoft.EntityFrameworkCore.EntityState.Modified; con.SaveChanges(); }
注:以上写法,如果在Model定义中未包含其他属性,EF会将其他属性全部清空,如果只需要修改定义的属性,可以使用下面这种写法
using(context con = new context())){ //新建模型实体 Model modelName = new Model(){ id=1, field = "fieldValue" }; //修改模型状态为尚未经过修改 con.Entry(modelName).State = EntityState.Unchanged; //告诉EF,哪些列做了修改 con.Entry(modelName).Property(p => p.filed).IsModified = true; con.SaveChanges(); }
2.4 删除(Delete) 1.未知主键数据,查询数据后删除
//删除单个数据 using(context con = new context())){ var modelName = con.Model.Where(linq表达式).FirstOrDefault(); con.Remove(modelName); con.SaveChanges(); } //删除多个数据 using(context con = new context())){ var modelName = con.Model.Where(linq表达式).ToList(); con.RemoveRange(modelName); con.SaveChanges(); }
注:EF中Remove(Add,Update)Range等都是一条条执行SQL执行的,如果需要操作大量数据考虑效率,建议使用con.Database.ExecuteSqlCommand("SQL 语句")来直接执行。 2.已知主键数据删除
using(context con = new context())){ Model modelName = new Model(){ id=1 }; //将给定实体以System.Data.EntityState.Unchanged状态附加到上下文中 con.Remove(modelName); con.Entry(modelName).State = Microsoft.EntityFrameworkCore.EntityState.Deleted; con.SaveChanges(); }
三.Model方法拓展 创建相同partial的Model类进行二次拓展。如果在实体模板类书写,会在重写生成模板后丢失。 四:EF中Model实体状态 EF中对实体状会有4种状态:
- Added:对象为新对象,并且已添加到对象上下文,但尚未调用
- Deleted:对象已从对象上下文中删除
- Detached:对象存在,但没有被跟踪。 在创建实体之后、但将其添加到对象上下文之前,该实体处于此状态
- Modified:对象上的一个标量属性已更改,但尚未调用
- Unchanged: 此对象尚未经过修改自对象附加到上下文中后,或自上次调用 (调用了SaveChange方法后所有的对象都改为Unchanged状态)
- 减少数据访问的延迟,在一次数据库的访问中返回所有的数据。
- 一次性读取所有相关的数据,可能导致部分数据实际无需用到,从而导致读取数据的速度变慢,效率变低
- 只在需要读取关联数据的时候才进行加载
- 可能因为数据访问的延迟而降低性能,因为循环中,每一条数据都会访问一次数据库,导致数据库的压力加大
Context ctx = new Context(); ctx.DeferredLoadingEnabled = false;4.针对外键懒加载字段的某个字段进行实时加载
db.context.Include(c=>c.外键对象).Include(c=>c.外键对象)...5.针对外键实时加载字段的某个字段进行懒加载 6. AssociateWith 用于筛选为特定关系检索到的对象。 7.LoadWith 用于立即加载与主目标相关的数据