zoukankan      html  css  js  c++  java
  • EntityFramework学习笔记4实体数据模型及增、删、改操作

    下面我们通过建立一个简单的例子来学习EF框架,直接进入主题吧:

    一 、创建实体数据模型

    1. 创建一个控制台应用程序,起名为EFDemo

    2. 创建一个实体模型

      在EFDemo项目上面右击选择添加—新建项—在已安装的选项中选择数据—ADO.NET实体对象模型,命名为EFStudy

    3. 与数据库连接

      第2步执行完毕会弹出向导,选择“从数据库生成”,点击“新建连接…”按钮,选择sql server,下略,测试连接成功后,确定返回,注意下方的App.Config会自动生成一个数据库名+Entities的名字,此名字会成为上下文的类名,建议修改为***+Context,比如PopContext,然后点击下一步

    4. 指定相应的库表、视图和存储过程生成实体

    勾选对应的库表、视图和存储过程生成实体,点击完成即可。

    注:可事先在sql server数据库中使用以下语句建一张简单的表

    CREATE TABLE [dbo].[SysDept](
    [ID] [varchar](16) primary key,
    [Name] [varchar](64) NOT NULL
    )
    GO

    以上步骤操作完毕后,在项目中新增文件EFStudy.edmx,并以图形化方式显示SysDept类

    二、增删改操作

    1.新增

    因为前面创建的是控制台应用程序,且为了清晰,只引入了一张表,代码也从简,直接在Program.cs里面写

    static void Main(string[] args)
            {
                //新增
                InsertDept();
            }
    
            private static void InsertDept()
            {
                //数据库表SysDept已经被EF映射为了SysDept类
                //此处可直接使用来定义对象
                SysDept sysDept = new SysDept();
                //为对象设置属性
                sysDept.ID = "1";
                sysDept.Name = "烟台**公司";
    
                //EF已经创建了上下文对象,类名为创建实体类型阶段指定的PopContext
                PopContext context = new PopContext();
                //将sysDept对象加入到上下文对象,三种方式
                //方式一(推荐)
                context.SysDept.AddObject(sysDept);
                //方式二
                //context.AddToSysDept(sysDept);
                //方式三
                //context.AddObject("SysDept", sysDept);
    
    
                //以上操作后数据变更在内存中,执行以下操作后保存到数据库
                int i=context.SaveChanges();
                Console.WriteLine("影响行数:"+i);
    
            }

    如上所示,将实体对象添加到上下文对象有三种方式,推荐第一种,符合习惯和自然,第二种在库表比较多的情况下,难以查找,第三种第一个参数采用字符串,易拼写错误且繁琐

    使用sql server 自带的SQL Server Profiler(开始—》SQL Server 2008-》性能工具,若找不到,说明你安装的sql server版本是express,开发版和企业版都有该工具),可查看数据库执行的每条sql,即可以观察上述程序执行时,EF将程序中对对象的操作转换为具体的sql语句,对于初期阶段理解学习以及后期的多表关联下性能调优大有益处。

     

    2.删除

     要删除某条记录,就要先找到该条记录,有两种方式,一是定义一个新对象,通过Context的Attach方法将该对象加入管理,如下面代码所示,二是在上下文对象中查找,代码在修改例子中体现

            private static void DeleteDept()
            {
                //先定义一个新对象并设置主键属性
                SysDept sysDept = new SysDept();            
                sysDept.ID = "1";
    
                //将此对象附加到上下文对象
                PopContext context = new PopContext();
                context.SysDept.Attach(sysDept);
    
                //移除对象,两种方法
                //方法一,推荐
                context.SysDept.DeleteObject(sysDept);
                //context.DeleteObject(sysDept);//方法二
    
                //以上操作后数据变更在内存中,执行以下操作后保存到数据库
                int i = context.SaveChanges();
                Console.WriteLine("影响行数:" + i);    
            
            }

    网上查找资料,发现好多是以下两种方式,可能在早期版本支持,在EF5.0中已过时,context既无Entry方法,也无Remove方法,sysDept.EntityState属性只读,不可设置

    1.context.Entry(sysDept).State = EntityState.Deleted;//EntityState枚举值需using System.Data;
    2.context.SysDept.Remove(sysDept)

     3.修改

      要修改某条记录,就要先找到该条记录

    private static void UpdateDept()
            {
                //找到要修改的记录,查找参数为lamda表达式,看不懂的可补习相关知识
                PopContext context = new PopContext();
                SysDept sysDept = context.SysDept.FirstOrDefault(dept => dept.ID == "1");
                //修改属性
                sysDept.Name = "青岛**公司";
    
                //以上操作后数据变更在内存中,执行以下操作后保存到数据库
                int i = context.SaveChanges();
                Console.WriteLine("影响行数:" + i);    
            }

    这里体现了上文所说查找记录的第二种方式,事实上,采用这种方式先找到对象,再对对象进行删除或者修改操作更符合常理。

    同删除类似,EF5.0中已没有context.Entry(sysDept).State = EntityState.Modified的写法

    4.事务处理

    上面说了增、删、改,程序中常用到的还有事务处理,与do.net处理类似

            private static void Transaction()
            {
                PopContext context = new PopContext();
                IDbTransaction trans = null;
                try
                {                
                    //打开连接
                    context.Connection.Open();
                    //开始事务
                    trans=context.Connection.BeginTransaction();
                    //执行操作
                    //修改一记录
                    SysDept sysDept = context.SysDept.FirstOrDefault(dept => dept.ID == "1");
                    sysDept.Name = "临沂****公司";
                    //新增一记录
                    sysDept = new SysDept { ID = "2", Name = "菏泽***公司" };
                    context.SysDept.AddObject(sysDept);         
                    //保存到数据库
                    int i=context.SaveChanges();
                    //提交事务
                    trans.Commit();
                    Console.WriteLine("已成功执行,影响行数:"+i);                
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    Console.WriteLine("发生异常,已回滚" + ex.Message);
                }
                finally
                {
                    context.Connection.Close();
                }
               
            }

    上述过程第一次执行正常提交,把sysDept.Name = "临沂****公司";中“临沂”改为“日照”,再执行一次,则会因为重复插入主键异常退出,查看数据库会发现,不仅新数据没插进去,而且在插入数据之前修改的数据也没有保存到数据库,从而说明实现了回滚功能。
    注意:此处回滚仅对数据库有效,内存中PopContext对象中的"临沂****公司"已经被更改了,回滚不会将内存中的数据恢复到事务前状态。

     三、小结
    从本节内容就能看出ORM的优点了,在程序中一方面不需要再写与数据库对应的的INSERT/DELETE/UPDATE的SQL语句,特别是在表字段比较多的情况下,写一个比较长的Insert语句,很容易发生错位、缺失问题,另一方面可以直接实例化对象,获取或者设置属性值时,智能提示很友好也很便利。

  • 相关阅读:
    3.2 线程复用:线程池
    3.1.7 线程阻塞工具类:LockSupport
    3.1.6 循环栅栏:CyclicBarrier
    3.1.4 读写锁
    3.1.5 倒计时器:CountDownLatch
    3.1.3 允许多个线程同时访问:信号量
    3.1.2 condition 条件
    3.1.1 重入锁 以及源码分析
    2.8.4 错误的加锁
    jsp中 scope="application" 表示
  • 原文地址:https://www.cnblogs.com/seawaving/p/2793373.html
Copyright © 2011-2022 走看看