• 第9章 Entity Framework综合应用


    第9章 Entity Framework综合应用

    image

    9.1 使用LINQ简化查询

    9.1.1 LINQ基础

    image

    >语法:

    >from 变量

    > in 数据源对象

    > where 条件表达式

    > orderby 排序列 [ascending]|[descending]

    > group 变量 by 分组条件

    > into 临时标识符

    > select 选择列

    9.1.2 LINQ to Objects

    1.LINQ to 字符串

    示例:

    string strDemo = "HelloWord!";

    //定义查询表达式

    var query = from n in strDemo select n;

    //遍历查询结果并输出

    foreach (char ch in query) {

    Console.WriteLine(ch);

    }

    示例:

    string strDemo = "HelloWord!";

    //定义查询表达式,输出大写字母

    var query = from n in strDemo where char.IsUpper(n) select n;

    //遍历查询结果并输出

    foreach (char ch in query) {

    Console.WriteLine(ch);

    }

    2. LINQ to List<T>

    List<Student> students = new List<Student>() {

    new Student{Name="张明",Gender="男",Birthday=DateTime.Parse("1996-2-1")},

    new Student{Name="王强",Gender="男",Birthday=DateTime.Parse("1995-6-11")},

    new Student{Name="张丽丽",Gender="女",Birthday=DateTime.Parse("1996-8-9")},

    new Student{Name="陈好",Gender="女",Birthday=DateTime.Parse("1994-12-24")},

    new Student{Name="张无忌",Gender="男",Birthday=DateTime.Parse("1994-4-24")}

    };

    //查询姓张的男学生,并按照出生日期升序排序

    var query = from stu in students

    where stu.Name.StartsWith("张") && stu.Gender == "男"

    orderby stu.Birthday ascending

    select stu;

    //遍历查询结果并输出

    foreach (Student stu in query)

    {

    Console.WriteLine(stu.Name);

    }

    3.LINQ to ArrayList

    ArrayList students = new ArrayList() {

    new Student{Name="张明",Gender="男",Birthday=DateTime.Parse("1996-2-1")},

    new Student{Name="王强",Gender="男",Birthday=DateTime.Parse("1995-6-11")},

    new Student{Name="张丽丽",Gender="女",Birthday=DateTime.Parse("1996-8-9")},

    new Student{Name="陈好",Gender="女",Birthday=DateTime.Parse("1994-12-24")},

    new Student{Name="张无忌",Gender="男",Birthday=DateTime.Parse("1994-4-24")}

    };

    //查询姓张的男学生,并按照出生日期升序排序

    var query = from Student stu in students

    where stu.Name.StartsWith("张") && stu.Gender == "男"

    orderby stu.Birthday ascending

    select stu;

    //遍历查询结果并输出

    foreach (Student stu in query)

    {

    Console.WriteLine(stu.Name);

    }

    9.1.3 认识查询方法

    查询表达式和查询方法示例

    数据源

    查询表达式写法

    查询方法写法

    String

    form n in strDemo

    select n;

    strDemo.Select(n=>n);

    String

    from n in strDemo where

    char.IsUpper(n)

    selectn;

    strDemo.Where(n=>Char.

    IsUpper(n));

    List<T>

    from stu in students

    where stu.Name.StartsWith(“张”)&&

    stu.Gender==”男”

    orderby stu.Birthday select stu;

    students.Where(stu=>stu.

    Name.StartsWith(“张”)&&

    stu.Gender==”男”).

    OrderBy(stu=>stu.Birthday);

    常用查询方法

    分类

    主要方法

    说明

    投影

    Select(),SelectMany()

    将结果集中的元素转化成所需要的形式。对应的查询关键字为where

    筛选

    Where()

    对应的查询关键字为where

    排序

    OrderBy(),OrderByDescending()等

    对应的查询关键字为orderby,ascending,descending

    集方法

    Union(),Distinct()等

    对集合进行合并,剔除等操作

    分组方法

    GroupBy()

    对应查询关键字为group by

    聚合方法

    Average(),Count(),Max(),Min(),

    Sum()等

    统计方法

    分区方法

    Skip(),Take(),First(),FirstOrDefault(),Single(),SingleOrDefault()

    用于选择结果集中指定范围的数据,其Skip(),Take()常用于分页处理;FirstOrDefault()常用于获取第一个实体;SingleOrDefault()用于获取唯一的实体

    9.2 使用LINQ to Entities查询数据

    9.2.1 从LINQ to Objects到LINQ to Entities

    示例:

    using (MySchoolEntities context = new MySchoolEntities())

    {

    //查询姓张的男学生,并按照出生日期升序排序

    var query = from stu in context.Student

    where stu.StudentName.StartsWith("张") && stu.Gender == "男"

    orderby stu.Birthday

    select stu;

    //遍历查询结果并输出

    foreach (Student stu in query) {

    Console.WriteLine(stu.StudentName);

    }

    }

    常用的LINQ to Entities支持的规范函数

    分类

    支持的方法或属性

    System.String静态方法

    Concat(),Equals(),IsNullOrEmpty()等

    String.String实例方法

    Contains(),EndsWith(),StartsWith(),IndexOf()

    ,Replace(),Substring(),ToLower(),ToUpper(),Trim()

    System.DateTime静态方法

    Equals()等

    System.DateTime实例方法

    Equals()等

    System.Math静态方法

    Floor(),Round(),Abs()等

    Guid静态方法

    NewGuid()

    9.2.2 单表查询和数据投影

    示例:

    using (MySchoolEntities context = new MySchoolEntities())

    {

    //按照条件查询学号、姓名和生日信息并输出

    DateTime compareDate = DateTime.Parse("1995-1-1");

    var query = from stu in context.Student

    where stu.Gender == "男" && stu.Birthday >= compareDate

    && stu.StudentName.Contains("张")

    orderby stu.StudentNo ascending, stu.Birthday descending

    select new { stu.StudentNo, stu.StudentName, stu.Birthday };

    Console.WriteLine("学号 姓名 生日");

    foreach (var stu in query.ToList())

    {

    Console.WriteLine("{0} {1} {2}", stu.StudentNo, stu.StudentName, stu.Birthday.ToString());

    }

    }

    >提示:

    如果是简单的查询用查询方法有时候会更简洁,例如使用Find()方法通过主

    键查询。

    9.2.3 查询多表数据

    1.使用导航属性

    stu.Grade

    2.join连接查询

    查询方法示例:

    context.Student.Join(context.Grade, s => s.GradeID, g => g.GradeID, (s, g) => new{}).ToList();

    linq语句示例:

    using (MySchoolEntities context = new MySchoolEntities())

    {

    //获取"学生姓名、年级"

    var query = from s in context.Student

    join g in context.Grade

    on s.GradeID equals g.GradeID

    where s.Gender == "男"

    select new {s.StudentName,g.GradeName };

    //输出信息

    foreach (var stu in query) {

    Console.WriteLine("姓名:{0} 年级:{1}",stu.StudentName,stu.GradeName);

    }

    }

    3.嵌套查询

    示例:

    using (MySchoolEntities context = new MySchoolEntities())

    {

    //查询GradeID为1的学生

    var query = from s in context.Student

    where s.GradeID == 1

    select new { s.Grade.GradeName, s.StudentName, s.StudentNo };

    var subQuery = from s in (query) where s.GradeName!="S1" select s;

    }

    9.2.4 聚合查询

    常用聚合函数

    方法

    说明

    int Count()

    计算个数

    int Max()

    计算最大值

    int Min()

    计算最小值

    int Sum()

    求和

    int Average()

    求平均

    9.3 处理关联数据

    1.添加管理数据

    GradeId=(from g in context.Grade where g.GradeName=”S1” select

    g.GradeId).SingleOrDefault();

    (from g in context.Grade where g.GradeName=”S1” select g)

    .SingleOrDefault().Student.Add(stu);

    2.级联删除

    using (MySchoolEntities context = new MySchoolEntities())

    {

    //Y2年级

    var grade = (from g in context.Grade where g.GradeName == "Y2" select g).SingleOrDefault();

    //删除Y2年级的学生

    while (grade.Student.Count > 0) {

    context.Student.Remove(grade.Student.FirstOrDefault());

    }

    //删除Y2年级

    context.Grade.Remove(grade);

    context.SaveChanges();

    }

    9.4 优化——从实体框架开始

    引起性能低的原因主要在以下几个方面。

    1. 复杂的对象管理机制

    2. 高度封装的执行机制

    3. 低效的SQL语句

    9.4.1 从LINQ to Entities到SQL

    1.使用ToString()直接输出T-SQL代码

    2.使用SQL Server Profiler跟踪SQL

    9.4.2 实体框架的状态管理

    示例:

    Grade grade = new Grade();

    //输出当前对象的状态

    Console.WriteLine(context.Entry(grade).State.ToString());

    状态

    说明

    具备该状态的对象

    Detached

    对象存在,但没有被跟踪

    新创建的对象

    Unchanged

    对象尚未经过修改

    从DbContext 中读取的对象、

    使用Attach()方法添加的对象、

    执行SaveChanges()后的对象

    Added

    对象为新对象,并且已添加到对象上下文

    使用Add()方法添加的对象

    Deleted

    对象已从上下文中删除

    使用Remove()方法移除的对象

    Modified

    对象上的一个属性已更改

    受DbContext管理,并被修改属性的对象

    DbEntitiyEntry的主要成员

    方法或属性

    说明

    DbPropertyValues CurrentValues

    获取由此对象表示的跟踪实体的当前属性值

    DbPropertyValues OriginalValues

    获取由此对象表示的跟踪实体的原始属性值

    EntityState State

    获取或设置实体的状态

    DbCollectionEntry Collection(

    string navigationProperty)

    获取一个对象,该对象表示从该实体到相关实体的集合导航属性

    DbReferenceEntry Reference(

    string navigationProperty)

    获取一个对象,该对象表示从该实体到其他实体的引用(即非集合)导航属性

    void Reload()

    从数据库重新加载该实体时会使用数据库中的值覆盖任何属性值

    利用状态管理机制的常用优化方式

    1.无跟踪查询

    (from s in context.Students select s)

    .AsNoTracking().FirstOrDefault();//适用于纯粹的查询数据

    2.关闭状态管理

    context.Configuration.AutoDetectChangesEnabled = false;

    //适用于批量操作数据

    3.使用替身删除

    var stu = new Student { StudentNo = 23230 };//适用于按主键删除数据

    context.Students.Attach(stu);

    context.Students.Remove(stu);

    9.4.3 延迟加载和贪婪加载

    EF数据加载机制

    1.延迟加载(默认)-用时加载数据

    2.贪婪加载-提前加载关联实体数据

    context.Configuration.LazyLoadingEnabled = false;

    var stu = (from s in context.Students.Include("Results")

    where s.StudentNo == 23221 select s).Single();

    9.4.4 使用本地数据缓存

    示例:

    //查询学生

    var query = (from s in context.Students select s);

    foreach (var stu in query)

    {

    Console.WriteLine("学生姓名:{0}", stu.StudentName);

    }

    //查询并输出学生人数

    Console.WriteLine("学生人数为:{0}",

    context.Students.Local.Count());

    9.4.5 从实体框架回归SQL

    DataBase成员

    方法或属性

    说明

    bool Exists()

    检查服务器上是否存在数据库

    void Create()

    在数据库服务器上为支持上下文中定义的模型创建一个新的数据库

    bool CreateIfNotExists()

    在该服务器上没有带相同名称的数据库时创建一个新的数据库

    bool Delete()

    删除该数据库

    void SetInitializer<TContext>

    (IDatabaseIntializer<TContext> stategy)

    设置数据库初始化策略

    int ExecuteSqlCommand(string sql,

    params object[] parameters)

    对数据库执行给定的DDL/DML命令,返回命令影响行数

    IEnumerable<IElement>

    SqlQuery<TElement>(string sql,params object[] parameters)

    执行sql查询,返回给定泛型类型的元素

    示例:

    using (MySchoolEntities context = new MySchoolEntities())

    {

    //执行SQL命令

    int result = context.Database.ExecuteSqlCommand(

    "Update Grade set GradeName='第二学年' where GradeName='Y2'");

    if (result > 0)

    {

    Console.WriteLine("数据更新成功!");

    }

    //查询某列数据

    Console.WriteLine("学好为23214的学生姓名:");

    var stuName = context.Database.SqlQuery<string>(

    "select StudentName from Student where StudentNo=23214");

    Console.WriteLine(stuName.ToList()[0]);

    //查询多行数据

    var parameter = new System.Data.SqlClient.SqlParameter("@GradeName","S1");

    var stus = context.Database.SqlQuery<Student>(

    "select * from Student where GradeId in (select GradeId from Grade where GradeName=@GradeName)",parameter);

    Console.WriteLine("S1的学生信息: 学号 姓名");

    foreach(var stu in stus){

    Console.WriteLine("{0} {1}",stu.StudentNo,stu.StudentName);

    }

    }

    除了Database.SqlQuery()方法外,还可以调用DbSet<TEntity>类型的某个方法执行查询。该方法的定义如下。

    DbSqlQuery<TEntity> SqlQuery(string sql,params object[] parameters)

    示例:

    using (MySchoolEntities context = new MySchoolEntities())

    {

    var parameter = new System.Data.SqlClient.SqlParameter("@GradeName", "S1");

    var stus = context.Student.SqlQuery(

    "select * from Student where GradeId in (select GradeId from Grade where GradeName=@GradeName)",parameter);

    Console.WriteLine("S1的学生信息: 学号 姓名");

    foreach(var stu in stus){

    Console.WriteLine("{0} {1}",stu.StudentNo,stu.StudentName);

    }

    }

    DBSet<TEntity>类型的SqlQuery()方法查询效率要低一点,因为该方法默认会被Entity Framework状态管理跟踪。

    借助SqlQuery()方法,同样可以执行SQL的存储过程。

    示例:

    using (MySchoolEntities context = new MySchoolEntities())

    {

    var parameter = new System.Data.SqlClient.SqlParameter("@gender", "男");

    var result = from s in context.Student.SqlQuery("execute GetStudents @gender", parameter) select s;

    foreach (var stu in result)

    {

    Console.Write("姓名:{0}", stu.StudentName);

    }

    }

  • 相关阅读:
    一行代码更改博客园皮肤
    fatal: refusing to merge unrelated histories
    使用 netcat 传输大文件
    linux 命令后台运行
    .net core 使用 Nlog 配置文件
    .net core 使用 Nlog 集成 exceptionless 配置文件
    Mysql不同字符串格式的连表查询
    Mongodb between 时间范围
    VS Code 使用 Debugger for Chrome 调试vue
    css权重说明
  • 原文地址:https://www.cnblogs.com/xuzhen97/p/8866786.html
Copyright © 2020-2023  润新知