本文介绍EntityFramework使用方法

  1. Entity Framework的注意点

    由于安装和操作的细节讲起来很琐碎,这部分只罗列出难点,其他细节请自行查阅
    安装细节
    Pluralize or singularize generated object names(确定所生成对象名称的单复数形式)复选框
    此复选框的意思是,将数据库中的复数表名映射成单数形式的实体类,如果有一对多,多对多关系的表会将属性名以复数形式显示,增加程序可读性
    Include foreign key columns in the model (在模型中包含外键)复选框
    将数据库外键关系映射到实体模型中
    Import selected stored procedures and functions into entity model (将所选存储过程和函数导入到实体模型中)
    将存储过程和函数导入到实体模型
    操作CRUD
    要先实例化上下文类
    using(var ctx = new SchoolDBEntities())
    {
    // 进行增删改查
    }
  2. 支持的查询方法

    支持的查询数据的方式有
    LINQ to Entites
    linq方法
    var linq = ctx.Students.Where(s => s.StudentID > 2);
    linq查询语句
    var linq = from item in ctx.Students select item;
    Entity SQL
    此法不建议使用
    Native SQL
    var tempResult = ctx.Students.SqlQuery("select * from Student");
    注意:sql语句返回的列不能改名,否则报错
    返回值类型的写法
    string result = db.Database.SqlQuery<string>("select studentname from Student where studentid = 1").FirstOrDefault<string>();
    执行非查询sql的写法
    int noOfRowUpdated = ctx.Database.ExecuteSqlCommand("Update student set studentname ='changed student by command' where studentid=1");
  3. ef表示体包含的方法

    ctx.Students表实体中除了上面讲到的SqlQuery方法外还包括如下方法
    Add方法
    db.Students.Add(student); // 添加一条记录到实体框架中
    AsNoTracking方法
    如果查询的数据只是用来展示的,可以使用AsNoTracking方法将查询的数据和DbContext断开连接,提高查询效率
    var result = db.Students.Select(s => new
    {
    s.StandardId,
    s.StudentName
    }).AsNoTracking().ToList();
    Attach方法
    将一条Student数据附加到EF的跟踪图中就像数据是从数据库中读取的一样,其实数据库中并不存在
    var result = db.Students.Attach(st);
    Create方法
    创建一个空的Student实例,该实例没有附加到Students集合中
    var result = db.Students.Create();
    Find方法
    返回Students表中主键id是5的数据,与之关联的数据也会一起返回
    如果数据已经添加到上下文中,但是没有保存到数据库,使用Find同样有效
    var result = db.Students.Find(5);
    Include方法
    指定包含在结果集中的导航属性
    var result = db.Students.Include("StudentAddress").ToList<Student>();
    也可以传递lambda表达式
    var result = db.Students.Include(s => s.Standard).ToList<Student>();
    Remove方法
    将提供的Student实例标记为已删除,改实例必须存在于上下文中
    var result = db.Students.Remove(st);
    SqlQuery带参数的用法
    var result = db.Students.SqlQuery("select * from student where studentid = @p", new SqlParameter("@p", SqlDbType.Int) { Value = 5} ).Select(s => s.StudentName).ToList();
  4. DBEntityEntry对象

    ef实体框架中,可以通过数据实体获取数据实体相关的DBEntityEntry对象,从而得到数据实体的所有信息
    var student = db.Students.Find(1);
    student.StudentName = "yejiawei";
    var entry = db.Entry(student); // 获取数据实体的DBEntityEntry对象
    属性
    var result = entry.Entity.GetType().FullName; // 获取实体的名称
    var result = entry.State.ToString(); // 获取实体当前的状态
    IEnumerable<string> result = entry.CurrentValues.PropertyNames; // 获取实体的所有属性名
    var result = entry.OriginalValues["StudentName"]; // 获取实体属性修改之前的值
    var result = entry.CurrentValues["StudentName"]; // 获取实体属性修改之后的值
    可以手动设置实体的状态为 Added,Modified,Deleted
    entry.State = EntityState.Modified;
    方法
    Collection
    返回导航属性的集合,多对多关系
    var result = entry.Collection("Courses");
    可以继续使用 result.Load() 预载数据
    还可以继续使用 result.Query().Where(...) 进一步筛选数据
    ComplexProperty
    返回复杂属性的集合
    GetDatabaseValues
    返回跟踪的属性集合
    var result = entry.GetDatabaseValues();
    Property
    返回实体指定属性的所有信息组成的集合
    var result = entry.Property("StudentName");
    Reference
    返回导航属性的集合,一对多或者多对一关系
    var result = entry.Reference("StudentAddress");
    可以继续使用 result.Load() 预载数据
    还可以继续使用 result.Query().Where(...) 进一步筛选数据
    Reload方法
    entry.Reload();
    调用此方法,之前的所有更改都无效,全部和数据库同步,并且当前状态是Unchanged
  5. 追踪变化

    在ef上下文的生命周期中,ef会自动追踪加载进来的实体,可以通过ChangeTracker来获取所有被上下文追踪的实体
    每一个实体都必须包含一个主键,如果没有主键ef是不会追踪的
    var student = db.Students.Find(1);
    属性
    var result = db.ChangeTracker.Entries(); // 获取所有被上下文追踪的实体
    var result = db.ChangeTracker.Entries().Count(); // 获取所有被上下文追踪的实体的个数
    var result = db.ChangeTracker.Entries(); // 获取当前上下文中的所有DBEntityEntry对象对象
  6. 维持Entity Framework的实体场景

    连接场景
    数据检索和增删改都在一个上下文里面操作
    在连接场景中完成增删改查是非常容易的,因为上下文自动跟踪实体的状态,AutoDetectChangesEnabled默认是true
    添加操作
    定义一个引用类型比较类
    public class StudentComparer : IEqualityComparer<Student>
    {
    public bool Equals(Student x, Student y)
    {
    if (x.StudentName.ToLower() == y.StudentName.ToLower())
    {
    return true;
    }
    return false;
    }
    public int GetHashCode(Student obj)
    {
    return obj.GetHashCode();
    }
    }
    新增操作
    if(!db.Students.ToList().Contains(new Student() { StudentName = "yejiawei" }, new StudentComparer()))
    {
    db.Students.Add(new Student() { StudentName = "yejiawei" });
    db.SaveChanges();
    return Ok("添加成功");
    }
    return Ok("已经存在了");
    修改操作
    Student StudetUpdate = db.Students.ToList().Where(s => s.StudentName == "yejiawei").FirstOrDefault();
    StudetUpdate.StudentName = "叶家伟";
    db.SaveChanges();
    删除操作
    db.Students.Remove(db.Students.ToList().ElementAt(0));
    db.SaveChanges();
    断开连接场景
    数据检索和增删改在不同的上下文里面操作
    在断开连接场景中,我们需要附加实体到新的上下文中,并且要指定状态
    Add方法,会自动的将实体块附加到新的上下文中并且自动的修改状态为Added,也就是说你调用Add方法,管他啥玩意儿都可以成功
    Attach方法,调用Attach方法会将实体块添加到上下文中,但是状态还是Unchanged,需要手动设置
    var test = db.Students.Attach(new Student() { StudentName = "yejiawei" });
    db.Entry(test).State = EntityState.Added;
    var result = db.Entry(test).State.ToString();
    db.SaveChanges();
    单个的实体
    单个的实体,直接更改状态,然后保存即可
    var test = new Student() { StudentName = "叶家伟" };
    db.Entry(test).State = EntityState.Added;
    var result = db.Entry(test).State.ToString();
    db.SaveChanges();
  7. Entity Framework并发问题

    在ef中可以根据数据库timestamp类型的列来处理并发问题,timestamp数据会在插入和更新时自动更改并且是唯一的
    数据库中timestamp类型的值是自动添加的
    然后,需要在ef中将timestamp列属性中的Concurency Mode设置为Fixed
    此时,ef在执行更新操作会将timestamp列设置成where的字句,来判断操作的数据有没有并发操作,如果发生了并发操作,那么会抛出DbUpdateConcurrencyException错误
    Student test1 = null;
    using(var context1 = new SchoolDBEntities())
    {
    context1.Configuration.ProxyCreationEnabled = false; // 查询的时候是否包含导航属性
    test1 = context1.Students.Where(s => s.StudentID == 9).Single();
    test1.StudentName = "小王";
    try
    {
    context1.Entry(test1).State = EntityState.Modified;
    context1.SaveChanges();
    }
    catch (DbUpdateConcurrencyException ex)
    {
    var t = ex;
    }
    }
  8. 执行存储过程

    如下的存储过程导入到ef中
    ALTER PROCEDURE [dbo].[GetCoursesByStudentId]
    -- Add the parameters for the stored procedure here
    @StudentId int = null
    AS
    BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    -- Insert statements for procedure here
    select c.courseid, c.coursename,c.Location, c.TeacherId
    from student s left outer join studentcourse sc on sc.studentid = s.studentid left outer join course c on c.courseid = sc.courseid
    where s.studentid = @StudentId
    END
    然后直接当做函数执行就可以了
    var courses = db.GetCoursesByStudentId(1);
    可以将更新,删除,新增的存储过程映射到实体上面,从而重写ef默认的增删改的方法
    存储过程中,新增的时候执行SELECT SCOPE_IDENTITY() AS StudentId,可以返回新增数据的id
  9. 在ef中使用枚举

    数据库中可以使用一些特殊的整数值,来表示数据的特殊含义,为了是代码的可读性更强,使用枚举来代替这些整数值
    首先,将实体中的一个属性列,Convert to Enum
    然后,在弹出的选择框中,输入枚举类型的名字,也就是你在写代码时要用到的枚举名称
    其次,在成员列表中,指定成员的名字,和成员对应的整数值
    现在,你可以使用你定义的枚举了
    var type = TeacherType.Guest;
  10. 在ef中使用表值函数

    首先要在数据库中添加一个表值函数
    ALTER FUNCTION [dbo].[GetCourseListByStudentID]
    (
    -- Add the parameters for the function here
    @studentID int
    )
    RETURNS TABLE
    AS
    RETURN
    (
    -- Add the SELECT statement with parameter references here
    select c.courseid, c.coursename,c.Location, c.TeacherId
    from student s left outer join studentcourse sc on sc.studentid = s.studentid left outer join course c on c.courseid = sc.courseid
    where s.studentid = @studentID
    )
    然后将这个表值函数导入到ef中,可以在模型浏览器中修改函数,然后在ef中使用表值函数,如下
    var result = db.GetCoursesByStudentId(1).Select(s => s);
  11. Local属性

    可以通过Local属性访问当前被追踪的实体,被标记为Deleted的实体不可以通过Local访问
    db.Students.Load(); // 预载,免去写ToList
    db.Students.Add(new Student() { StudentName = "New Student" });
    return Ok(db.Students.Local);
  12. 预先加载

    使用Include,表示加载导航属性
    (from s in context.Students.Include("Standard")
    where s.StudentName == "Student1"
    select s).FirstOrDefault<Student>();
  13. 懒加载

    当实体中包含包含复杂属性,只有当访问这个复杂属性的时候才会去查询
    如果要为整个上下文关闭懒加载,可以在上下文的类中设置
    public SchoolDBEntities(): base("name=SchoolDBEntities")
    {
    this.Configuration.LazyLoadingEnabled = false;
    }
    如果想只关闭某一个属性的懒加载,可以导实体的类中设置
    public virtual StudentAddress StudentAddress { get; set; }将这个virtual关键字去掉即可
  14. 异步查询和保存

    异步查询
    使用async标记此方法是异步的
    public async Task<Student> GetStudents()
    {
    Student result = null;
    using (var context = new SchoolDBEntities())
    {
    context.Configuration.ProxyCreationEnabled = false;
    // 使用await,可以释放当前线程从而可以执行其他代码,避免阻塞程序
    result = await context.Students.Where(s => s.StudentID == 10).FirstOrDefaultAsync<Student>();
    }
    return result;
    }
    异步保存
    public async Task<int> Get()
    {
    using (var context = new SchoolDBEntities())
    {
    var test = context.Courses.Attach(new Course() { CourseName = "数学" });
    context.Entry(test).State = EntityState.Added;
    return await context.SaveChangesAsync();
    }
    }
  15. 日志的记录

    第一种方式,使用默认配置
    在web.config配置文件中的entityFramework节点下添加
    <interceptors>
    <interceptor type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework">
    <parameters>
    <parameter value="F:\学习实验区\EntityFramework\Log.txt"/>
    <parameter value="true" type="System.Boolean"/>
    </parameters>
    </interceptor>
    </interceptors>
    即可自动的记录ef做的所有操作
    第二种方式,自定义日志记录
    using (var context = new SchoolDBEntities())
    {
    // 使用Log方法即可自动实现记录日志,然后追加到日志文件中
    context.Database.Log = (string message) =>
    {
    byte[] bts = Encoding.UTF8.GetBytes(message);
    using (FileStream fwrite = File.OpenWrite(@"F:\学习实验区\EntityFramework\Log1.txt"))
    {
    //fwrite.Write(bts, 0, bts.Length);
    fwrite.Position = fwrite.Length;
    fwrite.Write(bts, 0, bts.Length);
    }
    };
    var test = context.Courses.Attach(new Course() { CourseName = "数学" });
    context.Entry(test).State = EntityState.Added;
    return await context.SaveChangesAsync();
    }
  16. 事务提交和回滚

    ef默认的操作都是事务处理的,但是我们可以将ef多个操作再用一个事务封装起来,方便回滚
    using(DbContextTransaction dbTran = context.Database.BeginTransaction())
    {
    try
    {
    var test = context.Courses.Attach(new Course() { CourseName = "333" });
    context.Entry(test).State = EntityState.Added;
    await context.SaveChangesAsync();
    dbTran.Commit();
    return 1;
    }catch(Exception ex)
    {
    dbTran.Rollback();
    return 0;
    }
    }
  17. AddRange和RemoveRange

    AddRange批量增加
    List<Course> list = new List<Course>()
    {
    new Course() { CourseName = "yuwen" },
    new Course() { CourseName = "shuxue" },
    new Course() { CourseName = "yinyu" }
    };
    using (var context = new SchoolDBEntities())
    {
    context.Courses.AddRange(list);
    return await context.SaveChangesAsync();
    }
    RemoveRange批量删除
    using (var context = new SchoolDBEntities())
    {
    var items = context.Courses.Where(
    s => s.CourseName == "yuwen" || s.CourseName == "shuxue" || s.CourseName == "yinyu"
    ).AsEnumerable<Course>();
    context.Courses.RemoveRange(items);;
    return await context.SaveChangesAsync();
    }

C# EntityFramwork(Model First)使用要点的更多相关文章

  1. A Neural Probabilistic Language Model (2003)论文要点

    论文链接:http://www.jmlr.org/papers/volume3/bengio03a/bengio03a.pdf 解决n-gram语言模型(比如tri-gram以上)的组合爆炸问题,引入 ...

  2. Efficient Estimation of Word Representations in Vector Space (2013)论文要点

    论文链接:https://arxiv.org/pdf/1301.3781.pdf 参考: A Neural Probabilistic Language Model (2003)论文要点  https ...

  3. 关于DOM树的常见增删操作

    //具体关于DOM的内容可参考我的另外一篇文章"文本对象模型(Document Object Model)". 案例要点:     1.创建并增加元素节点     2.判断是否存在 ...

  4. Spring Boot笔记一

    Spring Boot 入门 Spring Boot 简介 > 简化Spring应用开发的一个框架:> 整个Spring技术栈的一个大整合:> J2EE开发的一站式解决方案: 微服务 ...

  5. [php]laravel框架容器管理的一些要点

    本文面向php语言的laravel框架的用户,介绍一些laravel框架里面容器管理方面的使用要点.文章很长,但是内容应该很有用,希望有需要的朋友能看到.php经验有限,不到位的地方,欢迎帮忙指正. ...

  6. Java Web编程技术学习要点及方向

    学习编程技术要点及方向亮点: 传统学习编程技术落后,应跟著潮流,要对业务聚焦处理.要Jar, 不要War:以小为主,以简为宝,集堆而成.去繁取简 Spring Boot,明日之春(future of ...

  7. Mysql –>EF edmx(model first)–> Sql server table

    一.mysql environment When we create an new database,first We need draw er diagram for somebody to sho ...

  8. Neutron LBaaS Service(2)—— Neutron Services Insertion Model

    Service Insertion Service Insertion是Neutron中实现L4/L7层服务的框架.Neutron以前只有一级插件结构用于实现各种L2层技术(如LinuxBridge, ...

  9. 一个多阶段库存订货问题的 +Leapms 求解要点

    一个多阶段库存订货问题的 +Leapms 求解要点 问题来自微信公众号“运筹分享交流”——“互助·运筹擂台3 多阶段库存订货问题”. 数学概念模型 求解结果 +Leapms>mip relexe ...

随机推荐

  1. ZooKeeper服务-一致性、实现

    实现 ZooKeeper服务有两种不同的运行模式.一种是“独立模式”(standalone mode),即只有一个ZooKeeper服务器.这种模式比较简单,适合于测试环境,但是不能保证高可用性和可恢 ...

  2. Java内部锁的可重用性(Reentrancy)

    Java提供了强制原子性的内部锁机制:synchronized块.但是内部锁是可重入的,当线程试图获得它自己占有的锁时,请求会成功. 简单的说,就是在一个synchronized方法内部调用本类的其他 ...

  3. STL视频_00

    [05:40]比赛规则 - Part01[06:33]比赛规则 - Part02[07:28]比赛规则 - Part03[08:45]提出的问题 - 1和2[09:23]提出的问题 - 3和4 *** ...

  4. write.table函数语法:

    write.table (x,  file ="",  sep ="",  row.names =TRUE,  col.names =TRUE,  quote ...

  5. Python爬虫之BeautifulSoup的用法

    之前看静觅博客,关于BeautifulSoup的用法不太熟练,所以趁机在网上搜索相关的视频,其中一个讲的还是挺清楚的:python爬虫小白入门之BeautifulSoup库,有空做了一下笔记: 一.爬 ...

  6. substr 方法

    substr 方法 返回一个从指定位置开始,并具有指定长度的子字符串. 参数 start 必选.所需的子字符串的起始位置.字符串中第一个字符的索引为 0. length 可选项.返回的子字符串中包含的 ...

  7. 51nod 1428 贪心

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1428 1428 活动安排问题 基准时间限制:1 秒 空间限制:13107 ...

  8. JVM_总结_01_JDK的安装

    一.前言 本文主要简要介绍下JDK的安装 二.下载 1.JDK下载地址 前往官方网站下载JDK jdk8官网下载 2.JDK下载 如下图 下载完之后得到安装软件,如下图 三.安装 双击运行安装软件,即 ...

  9. L124

    I have a toothache because there is a cavity in one of my teeth. I founded an orphanage last year an ...

  10. SQLAlchemyの增删改查

    用a*my写原味sql from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, I ...