ado.net EF 增删改查、分页

Linq(集成语言查询)在与数据库交互增删改查中使用的非常多。Linq分为Linq to SQL(已经过时)、Linq to EF、Linq to XML等多种类型。LInq to EF 是针对EF实体框架而构建的。使用EF(实体框架)可以及其方便地创建和修改SQL数据库,它封装了繁琐的SQL代码,通过数据库和对象之间的映射,让程序员可以完全按照面向对象的思路使用linq语句操纵数据库中的数据。本文就使用LInq to EF做一下基本的增删改查。不对之处请各位高手拍砖指教。

本次的增删改查采用EF三种设计模式中的DBFirst设计模式(EF中的DBFirst实例)。下面进行基本的增删改查(列出的所有代码已经过测试)。

 

一、添加

            Student1 str = new Student1();   //新建实例
            str.Sno = Txtno.Text;            //为该实例的各个属性赋值
            str.Sname = Txtname.Text;
            str.Ssex = Convert.ToInt16(Txtsex.Text);
            str.Sphone = Txtphone.Text;
            str.Saddress = Txtaddress.Text;
            dbcontext.Student1.AddObject(str); //添加到对象上下文中
            dbcontext.SaveChanges();           //保存修改
            //第二种方式
            //{
            //dbcontext.Student1.Attach(str);
            //dbcontext.ObjectStateManager.ChangeObjectState(str,EntityState.Added);
            //dbcontext.SaveChanges();
            //}
            //新建实例简单方法
            //Student1 str = new Student1()
            //{
            //    Sno = Txtno.Text,
            //    Sname =Txtname.Text,
            //    Ssex =Convert.ToInt16(Txtsex.Text),
            //    Saddress=Txtaddress.Text,
            //    Sphone= Txtphone.Text
            //};

总结:第一种方法中使用AddObject()方法添加实体到当前上下文中包含了两个操作:

(1)把该实体附加到上下文中

(2)修改实体的状态为添加

第二种方法是第一种方法的展开操作而已,两种方法都OK。

在这里,我们可以简单的记上面的方法:上下文=数据库、实体名=表中。只是为了简单记而已,实际上两者并不等价。

 

二、查询

            #region 简单的无where的查询 Linq表达式
            var resultt = from c in dbcontext.Student1 select c;
            if (resultt == null) //查询结果不存在
            {
                //
            }
            else
            { 
                //
            }
            #endregion

            #region 简单的无where的查询 Lamada表达式
            var first = dbcontext.Student1.FirstOrDefault();//查询出第一条数据 如果不存在则输出默认值
            #endregion

            #region 带where的Linq 查询
            var resultWhere = from c in dbcontext.Student1 where c.Sno == TextBox1.Text select c;
            if (resultWhere == null) //查询结果不存在
            {
                //
            }
            else
            {
                //
            }
            #endregion

            #region 带Where的lamada查询
            var result1 = dbcontext.Student1.Where(s => s.Sno == TextBox1.Text).FirstOrDefault();  //后面的FirstOrDefault()如果使用的是主键查询可以省略。
            //FirstOrDefault 默认的就是查询第一条记录,否则为默认
            var result2 = dbcontext.Student1.FirstOrDefault(s => s.Sno == TextBox1.Text);//两种方式都可以
            #endregion

总结:通过Linq或Lambda表达式查询出来的结果都是实现了IQueryable<T>接口的实体集。

关于IQueryable<T>接口我们有必要详细说一下,在该接口内部只有这么几行简单的代码。

    public interface IQueryable : IEnumerable
    {
        // 摘要:
        //     获取在执行与 System.Linq.IQueryable 的此实例关联的表达式树时返回的元素的类型。
        //
        // 返回结果:
        //     一个 System.Type,表示在执行与之关联的表达式树时返回的元素的类型。
        Type ElementType { get; }
        //
        // 摘要:
        //     获取与 System.Linq.IQueryable 的实例关联的表达式树。
        //
        // 返回结果:
        //     与 System.Linq.IQueryable 的此实例关联的 System.Linq.Expressions.Expression。
        Expression Expression { get; }
        //
        // 摘要:
        //     获取与此数据源关联的查询提供程序。
        //
        // 返回结果:
        //     与此数据源关联的 System.Linq.IQueryProvider。
        IQueryProvider Provider { get; }
    }

虽然通过上面的注释大家也都了解的差不多了,但是,我还是想再唠叨一下。当一个查询请求过来时,会先有Provider执行查询表达式(Expression),接着才会生成sql脚本,到数据库中去查询数据。注意,前面的一句话到数据库中查询数据是不准确的。为什么这么说呢?延迟加载,这就是原因。IQueryable是离线型的集合,真正sql语句的执行是在数据真正用到的时候才会执行。

三、修改

 //Student1 str = new Student1();//首先创建一个实体类
            Student1 str = (from c in dbcontext.Student1 where c.Sno == Txtno.Text select c).SingleOrDefault<Student1>();//本次查询是针对主键进行的查询,///查询结果只有一个或者为空,也可以设置其他查询条件,进行多个数据的修改操作
            if (str == null)
            {
                Label1.Text = "数据库中不存在该用户!";
                return;
            }
            else
            {
                str.Sno = Txtno.Text;
                str.Sname = Txtname.Text;
                str.Ssex = Convert.ToInt16(Txtsex.Text);
                str.Sphone = Txtphone.Text;
                str.Saddress = Txtaddress.Text;
                //dbcontext.Student1.Attach(str); //将该实体类附加到对象上下文中
                dbcontext.ObjectStateManager.ChangeObjectState(str, EntityState.Modified);//修改对应实体的的状态
                dbcontext.SaveChanges(); //保存修改
            }

四、删除

            ObjectQuery<Student1> st = dbcontext.Student1;//在此使用的是主键查询,也可以使用其他字段查询,删除多个数据
            IQueryable<Student1> str =from c in dbcontext.Student1 where c.Sno == Txtno.Text select c;
            Student1 st1 = (from c in dbcontext.Student1 where c.Sno == Txtno.Text select c).SingleOrDefault<Student1>();
            if (st1 == null)
            {
                Label1.Text = "数据库中不存在该用户!";
                return;
            }
            else
            {
                dbcontext.ObjectStateManager.ChangeObjectState(st1, EntityState.Deleted);//修改对应实体的的状态
                dbcontext.SaveChanges();
                //也可以使用下面的方式 第二种方式比较简单
                //dbcontext.Student1.DeleteObject(st1);
                //dbcontext.SaveChanges();
            }

五、分页查询

           //要跳过多少页
            int skipPage;
            //每页两条数据
            int countPerPage = 2;
            //从跳过0页到跳过2页(输出第1-3页)
            for (skipPage = 0; skipPage <= 2; skipPage++)
            {
                var result = dbcontext.Student1
                    //分页必须排序
                    .OrderBy(t => t.Sno)
                    //跳过指定页数
                    .Skip<Student1>(skipPage * countPerPage)
                    //获取条数
                    .Take<Student1>(countPerPage);
                int count = skipPage + 1;
                Response.Write("第" + count + "页:");
                //输出查询结果(该页)
                foreach (var item in result)
                {
                    Response.Write("学号:" + item.Sno + ",姓名:" + item.Sname + ",性别:" + item.Ssex + "\r\n");
                    //Label1.Text += "学号:" + item.Sno + ",姓名:" + item.Sname + ",性别:" + item.Ssex;
                    //Label1.Text += "\r\n";
                }
            }

六、使用匿名类查询多个字段

            #region
            var resultt = from c in dbcontext.Student1 where c.Sname == "小意" select new { c.Sno, c.Sname, c.Ssex };
            //var result=from c in dbcontext.Studnent1 where c.Sname="小意" select new {id=c.Sno,name=c.Sname,sex=c.Ssex}//也可以使用这种方式
            if (resultt == null) //查询结果不存在
            {
                //
            }
            else
            {
                //
                foreach (var item in resultt)
                {
                    Label1.Text += "学号:" + item.Sno + "姓名:" + item.Sname + "性别:" + item.Ssex;//此时Saddress、Sphone等字段无法访问
                }
            }
            #endregion

前面我们查询的都是整个Student对象,在实际使用过程中,我们可能只需要查询某些字段,这个时候我们就需要匿名类了。

 

七、防延迟加载查询

 

这个查询结果可以保存到服务器内存中

            var result1 = (from u in dbcontext.Student1
                           where u.Ssex==1
                           select u).ToList<Student1>();

            foreach (var item in result1)
            {
                Response.Write("学号:" + item.Sno + ",姓名:" + item.Sname + ",性别:" + item.Ssex + "\r\n");
            }

上面我们介绍的一些普通的延迟查询,查询的结果都是IQueryable类型,这个类型中只放三样东西:查询表达式、元素的类型、查询的驱动。我们得到的查询结果是在我们遍历的时候才执行得到的。使用ToList()查询的时候就已经执行了查询,得到了结果,防止了延迟加载的发生。防延迟加载技术主要使用在缓存技术中。

 

八、总结

 

上面列出的增删改查有的可能不止一种实现方式,具体使用哪种方式可以根据自己的偏好,当然有时候要考虑性能,择优采用。

Linq语句不容易编写,想要编写正确的Linq语句可以借助LINQPad工具

 

注意:在EF 4.0 和EF4.0+版本中,上面的方法可能会有些许的变化

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值