zoukankan      html  css  js  c++  java
  • EF 学习系列三 数据操作数据加载及EF中执行Sql

    1、实体状态

    我们通过EF来对数据库进行操作并持久化到数据库,那么EF必然通过EF上下文来维护实体的状态,明确知道每一个状态所对应的操作。也就是说EF通过上下文负责跟踪实体的状态。EF实体状态存在命名空间System.Data.Entity下的EntityState枚举中

    1.1、Added

    Added状态针对添加操作,当标记为此状态时,表名实体被上下文追踪但是不存在数据库中,当调用SaveChange()的时候会插入到数据库中。标记Added状态有两种:一种是间接标记,通过Add方法调用;另一种显示标记通过Entry方法调用代码如下

     var cus = new Customer() {
                        Name="魏杨杨",
                        Age=18,
                        Email="30119459@qq.com",
                        AddTime=DateTime.Now
                    };
                    db.Customer.Add(cus);
                    db.SaveChanges();
    //或者是
    var cus = new Customer() {
                        Name="魏杨杨",
                        Age=18,
                        Email="30119459@qq.com",
                        AddTime=DateTime.Now
                    };
                    db.Entry(cus).State = System.Data.Entity.EntityState.Added;
                    db.SaveChanges();

    1.2、UnChangeed

    实体类被EF上下文所追踪,但是存在数据库中的值未发生改变。若一个实体类不存在与数据库,但是该实体要被上下文所追踪,同时该实体值未发生改变就可以通过Attach进行附加追踪,然后标记为UnChanged状态

    using (var db =new  WYDBContext())
                {
                    var cus = new Customer() {
                        Name="魏杨杨",
                        Age=18,
                        Email="30119459@qq.com",
                        AddTime=DateTime.Now
                    };
              db.Customer.Attach(cus);
                    db.Entry(cus).State = System.Data.Entity.EntityState.Unchanged;
                    db.SaveChanges();
                }

    1.3、Modified

    实体被EF上下文所追踪并存在于数据库中,同时部分或者所有属性值已经被更改,当调用SaveChange()时则更新到数据库中。注意:在EF6.0以上的版本中不存在Update方法。看数据库里面的值

    using (var db =new  WYDBContext())
                {
                    var cus = new Customer() {
                        Zj=1,
                        Name="魏杨杨22",
                        Age=18,
                        Email="30119459@qq.com",
                        AddTime=DateTime.Now
                    };
                    
                    db.Entry(cus).State = System.Data.Entity.EntityState.Modified;
                    db.SaveChanges();
                }

     一般我做更改的时候都不会这么麻烦,当修改的时候只要传来这一列的参数ID 查找出当前列就直接修改了,我这种方法用的多一点:比如

    public ActionResult Edit(int id)
            {
                using (var db = new WYDBContext())
                {
                    var model = db.Customer.Find(id);
                    model.Name = "Wyy333";
                    model.Age = 19;
                    db.SaveChanges();
                    return View(model);
                }
                   
            }

    1.4、Deleted

    实体类被EF上下文所追踪并存在于数据库中,当标记为Deleted状态时,调用SaveChange()方法时数据将在数据库中删除,和Added状态一样可以调用Remove或者RemoveChange方法标记实体为Deleted状态,或者通过Entry方法标记

    using (var db =new  WYDBContext())
                {
                    var cus = new Customer() {
                        Zj=1,
                        Name="魏杨杨22",
                        Age=18,
                        Email="30119459@qq.com",
                        AddTime=DateTime.Now
                    };
                    
                    db.Entry(cus).State = System.Data.Entity.EntityState.Deleted;
                    db.SaveChanges();
                }
    
    //或者
    using (var db =new  WYDBContext())
                {
                    var cus = new Customer() {
                        Zj=1,
                        Name="魏杨杨22",
                        Age=18,
                        Email="30119459@qq.com",
                        AddTime=DateTime.Now
                    };
    
                    db.Customer.Remove(cus);
                    db.SaveChanges();
                }
    
    //或者这种删除是最常见了的吧我见过的都是这样的
    using (var db = new WYDBContext())
                {
                    var model = db.Customer.Find(id);
                    db.Customer.Remove(model);
                    db.SaveChanges();
                    return View(model);
                }

     2、加载关联数据

    在EF6.0 以上的版本中,数据加载方式有3种:延迟加载,饥渴加载、显示加载。三种加载方式都有其场景,利用不同将导致性能问题。

    2.1、Lazy Loading(延迟加载)

    顾名思义就是当我门需要的时候才加载也就是说的按需加载。当第一次访问指向实体或者实体的属性时,实体或者实体的集合将从数据库加载,访问导航属性是相关的对象或者子对象不会自动加载。virtual 的导航属性就是延迟加载。摸人家情况下EF启动延时加载。我们也可以在EF上下文派生类中手动关闭延迟加载

    在订单里面加点数据

    当查询Customer的时候看到Order还没有计算,

     下面来获取Order数据

    现在我们关闭延时加载效果 再看看

    public WYDBContext():base("SqlConn")
            {
                Configuration.LazyLoadingEnabled = false;
            }

     

    这不就报错了吗。现在我们就看到延迟加载的本质:只有当调用者使用的时候才会计算结果。

    2.2、Eager Loading(饥饿加载)

    查询实体的时候可以加载相关实体或者子实体作为查询的一部分,加载父对象同时加载子对象,在EF中可以使用DbSet<T>.Include()方法来实现饥渴加载。和延迟加载不同的是我们用与不用子对象都会被加载进来。

    using (var db =new  WYDBContext())
                {
                    var cs = db.Customer.Include("Order").ToList();
                    var cs2 = db.Customer.Include(p=>p.Order).ToList();//using System.Data.Entity;
    
                }

    现在可以看出饥饿加载的本质:提前加载所有数据

    2.3 Explicitly Loading(显示加载)

    延迟执行有延迟加载个显示加载两种方式,即使我们禁用了延迟加载,然然可以通过显示加载来延迟加载相关实体,通过DbEntityEntry<T>.Reference("").Load()加载实体。通过DbEntityEntry<T>.Collection("").Load()加载集合

     using (var db =new  WYDBContext())
                {
                    var cs = db.Customer.ToList().FirstOrDefault();
                    var order = db.Entry(cs).Collection(x => x.Order).Query().ToList();
    
                    var or = db.Order.ToList().FirstOrDefault();
                    db.Entry(or).Reference(x => x.Customer).Load() ;
    
                }

     效果如期而至就不贴了。可以总结出显示加载的本质:即使禁用延迟加载任然可以延迟执行

     3、在Ef中执行Sql

    3.1、在实体上执行原始查询

    在EF中可以通过SqlQuery来查询数据 有如下两种方法

    efDbContext.Database.SqlQuery<实体类名>(string sql , params object[] parameters)

    efDbContext.实体类.SqlQuery(string sql , params object[] parameters)

    Tolist()后将所有数据加载到内存中;

    using (var db =new  WYDBContext())
                {
                    //结果会保存到数据库中
                    var c2 = db.Customer.SqlQuery("Select * from Customer").ToList();
                    c2.Last().Email = "wyy22@qq.com";
                    db.SaveChanges();
    
                    //结果不会保存到数据库中
                    var c1= db.Database.SqlQuery<Customer>("Select * from Customer").ToList();
                    c1.Last().Email = "wyy@qq.com";
                    db.SaveChanges();
                }

    这里要把列名弄了跟数据库里面的对应就是不要去别名了 我出错是因为这里一个是Name一个是NameWyy哈哈 挖坑给自己跳

     [Column("NameWYY", TypeName = "nvarchar")]//我加了WYY看效果
            [StringLength(50, ErrorMessage = "{0}长度不能超过50个字符")]
            [Display(Name = "姓名")]
            public string Name { get; set; }

    注意:

    efDbContext.Database.SqlQuery<实体类名>(string sql , params object[] parameters) 此方法查询在数据库database上,实体不会被上下文跟踪

    efDbContext.实体类.SqlQuery(string sql , params object[] parameters)查询在上下文的实体集合DbSet上,实体会被上下文跟踪

    3.2、在EF中执行Sql:删除,修改

    using (var db =new  WYDBContext())
                {
                    //第一种
                    string ema = "wwww@qq.com";
                    string sql = $"Update Customer set email='{ema}' where Zj=1;";
                    db.Database.ExecuteSqlCommand(sql);
                    //第二种 可以防止Sql注入
                    SqlParameter[] para = { new SqlParameter("@Emale", "wwww@qq222.com"),new SqlParameter("@Zj",1) };
                    var sql1 = "Update Customer set email=@Emale where Zj=@Zj;";
                    db.Database.ExecuteSqlCommand(sql1,para);
                }

     删除也是一样的

  • 相关阅读:
    奥东......NGUI Scroll View
    奥东......Unity中小技巧
    java-web 小知识点
    奥东here......Unity中的协程
    JAVA 犯错汇总
    python 模拟 java hashcode
    pyqt文件转换成python代码
    loadrunner 运行javavuser报错Failed to get JRE version解决方法
    python 实现 loadrunner xml脚本格式化
    loadrunner web_custom_request 脚本处理
  • 原文地址:https://www.cnblogs.com/w5942066/p/12162595.html
Copyright © 2011-2022 走看看