当前位置:Gxlcms > 数据库问题 > mvc EF 执行SQL语句

mvc EF 执行SQL语句

时间:2021-07-01 10:21:17 帮助过:2人阅读

2. DbDatabase.SqlQuery   没有跟踪状态的查询  

3. DbDatabase.SqlCommand 直接执行SQL语句 一般用来  批量 增删改

下面 让我们来看下使用方法

再上篇的公共资源库里  添加方法

技术分享
public virtual IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters)
        {
            return dbSet.SqlQuery(query, parameters);
        }


        public virtual IEnumerable<TEntity> GetwhithdbSql(string query, params object[] parameters)
        {
            return context.Database.SqlQuery<TEntity>(query, parameters);
        }
View Code

通过对比 来介绍下 第一个和第二个的区别~~

在课程控制器下 分别执行这两个方法

技术分享
var query = "SELECT * FROM Course WHERE CourseID = @p0";
            Course course = unitofwork.CourseRepository.GetWithRawSql(query,id).Single();
            EntityState state = unitofwork.GetState(course);
            string name=course.Department.Name;

            Course coursetwo = unitofwork.CourseRepository.GetwhithdbSql(query, id).Single();
            EntityState statetwo = unitofwork.GetState(coursetwo);
            string nametwo = coursetwo.Department.Name;
View Code

执行后的结果

1.先来看第一个  他的状态是unchanged  也就说 他加入了context上下文中  有跟踪状态

技术分享

并且下面顺利读取出course.Department.Name   也就是可以读取到导航属性

2.再看来看第二个 他的状态是detached 并没有加入到 context上下文中  没有有跟踪状态

技术分享

所以 我们下面的读取导航属性的内容时  会报错~~

3.再来说说DbDatabase.SqlCommand  这个比较简单 增删改用这个不错  下面说个批量更新的例子~

假设有需求 更新所有的课程学分为N时   在这种批量操作时 用ORM 框架 就会不太方便了 这时我们可以用这个直接执行SQL语句

这个业务属于课程的  所以继承通用资源库类  代码如下

技术分享
using System;
using ContosoUniversity.Models;

namespace ContosoUniversity.DAL
{
    public class CourseRepository : GenericRepository<Course>
    {
        public CourseRepository(SchoolContext context)
            : base(context)
        {
        }

        public int UpdateCourseCredits(int multiplier)
        {
            return context.Database.ExecuteSqlCommand("UPDATE Course SET Credits = Credits * {0}", multiplier);
        }

    }
}
View Code

修改上篇的UnitOfWork类

 

技术分享
private CourseRepository courseRepository;

public CourseRepository CourseRepository
{
    get
    {

        if (this.courseRepository == null)
        {
            this.courseRepository = new CourseRepository(context);
        }
        return courseRepository;
    }
}
View Code

控制器如下

技术分享
public ActionResult UpdateCourseCredits(int? multiplier)
{
    if (multiplier != null)
    {
        ViewBag.RowsAffected = unitOfWork.CourseRepository.UpdateCourseCredits(multiplier.Value);
    }
    return View();
}
View Code

最后添加视图~~

运行结果图

技术分享

二.无跟踪查询

EF再默认的时候给我们开启了跟踪查询  这个跟踪的是什么呢? 先来介绍下这个  看下面的代码

技术分享
Department  duplicateDepartment = db.Departments
                    .Where(d => d.InstructorID == department.InstructorID)
                    .FirstOrDefault();

               duplicateDepartment.Name = "wuhawuha";

         bool IsUpdate=db.Entry<Department>(duplicateDepartment).Property(p => p.Name).IsModified; //是否修改
         string now= db.Entry<Department>(duplicateDepartment).Property(p => p.Name).CurrentValue; //现在的值
         string before = db.Entry<Department>(duplicateDepartment).Property(p => p.Name).OriginalValue; //以前的值
View Code

我们先随便查出一个院系信息 修改他的名字 这是我们会通过上面的信息 得到现在的值  以前的值  这就是跟踪帮我们做的事  下面看下无跟踪的

技术分享

实现无跟踪很简单  在查询时 加上asNoTracking() 即可. 加上后我们发现 明明发生变化了 但是IsUpdate依然为false。而且在 获取以前的值时 抛出了异常。

通常情况 我们并不需要跟踪这些状态 可以在查询时去掉跟踪查询,可以使得性能 得到提升~ 以前一直觉得去掉这个会影响导航属性的使用 但是测试后  并没有影响~

这个跟踪查询 还会带来另一个问题    看下面的图

技术分享

这是在修改前  加了句  先查询这个修改的 再修改 这是就会报错  ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。

遇到这个错误  在查询时 加上asNoTracking() 即可.  目前在用EF时 个人并不喜欢有跟踪状态~~ 喜欢加上asNoTracking()

三.使用代理

了解过ORM框架的  我们知道 导航属性 使用了代理模式 ,这个代理 也是跟导航属性有关的 。 禁用代理 可以提高序列化的速度 .

关闭代理的代码为在继承 dbcontext 的类里  加上如下代码

 public SchoolContext()
        {
             this.Configuration.ProxyCreationEnabled = false;
        }

下面展示下有代理和没有代理的区别  先看有代理时

技术分享

我们的Administrator 是导航属性  我们看到 得到的是一串很长的数字和字母的组合  在下面 访问这个Administrator属性时 会通过延迟加载 才得到Administrator属性

再来看代理关闭时的图

技术分享

看我们的导航属性 都为null 不能正确获得导航属性

四.自动检测功能

  • DbSet.Find
  • DbSet.Local
  • DbSet.Remove
  • DbSet.Add
  • DbSet.Attach
  • DbContext.SaveChanges
  • DbContext.GetValidationErrors
  • DbContext.Entry
  • DbChangeTracker.Entries

在上面的方法中 会调用自动检测功能。  这个功能默认是开启的  当我们在做批量操作时 可以关闭这个来提高性能 .例如

using (var context = new UnicornsContext())
{
    try
    {
        context.Configuration.AutoDetectChangesEnabled = false;

        // Make many calls in a loop
        foreach (var unicorn in myUnicorns)
        {
            context.Unicorns.Add(unicorn);
        }
    }
    finally
    {
        context.Configuration.AutoDetectChangesEnabled = true;
    }
}

 http://my.oschina.net/wzzz/blog/113561

mvc EF 执行SQL语句

标签:

人气教程排行