在ASP.NET MVC中以数据库优先模式执行原始SQL查询

7
我的项目模型是基于数据库的,使用远程访问另一台服务器上的数据库。 由于我的查询非常复杂,并且我更喜欢使用SQL而不是LINQ,因此我需要使用原始SQL查询。
以下是我的操作步骤:
        string query = "select * from Inquiry_TBL where ...";

        using (educationEntities db = new educationEntities())
        {
            var list = db.Database.SqlQuery<Inquiry_TBL>(query);
            ViewData["total"] = list.Count();
        }

有时候我会在一秒内得到查询结果,但有时它会一直加载很久,然后出现一个错误信息:“'Calling 'Read' when the data reader is closed is not a valid operation.'”是什么原因导致的呢?我的代码有问题吗?还是因为我正在使用远程访问另一个服务器?如果切换到本地服务器会解决这个问题吗?

告诉我们 SQL 是什么,我们可能会提供 Linq 或 Lambda 以及解释。 - BlackICE
你每次调用查询时,查询语句是否相同或者where子句中有不同之处?我建议在服务器上运行SQL Profiler以查看确切的运行情况。然后,你可以将查询粘贴到SSMS中,并启用show execution plan来运行它,从而诊断返回的结果。如果缺少索引,执行计划也应该显示出来。 - BlackICE
我切换回本地服务器,它可以正常工作。谢谢。现在我的问题是我的SQL查询语句是这样的:"select * from Table_A inner join Table_B ...",这意味着我将从两个表中获取数据,并将这些数据返回到视图中。但是执行SQL查询语句:"db.Database.SqlQuery<Table_A>(query)"只能从"Table_A"表中返回数据。如果我想要从"Table_A"和"Table_B"中获取数据,我该怎么办? - user2093360
我觉得EF并不适合你想要做的事情,你只是想从表中获得计数吗?EF是用于从数据库中的数据重新生成对象的。 - BlackICE
是的,我只是想获取计数。我通过创建一个公共类来解决问题,该类包含我将需要的所有连接表字段,并将该类用作返回元素。您所说的重新填充对象是什么意思? - user2093360
1个回答

11
实体框架Code First API包括一些方法,使您可以直接将SQL命令传递到数据库。您有以下选项: • 使用DbSet.SqlQuery方法进行返回实体类型的查询。返回的对象必须是DbSet对象所期望的类型,并且它们会自动由数据库上下文跟踪,除非您关闭跟踪。(请参阅关于AsNoTracking方法的下一节。) • 使用Database.SqlQuery方法进行返回非实体类型的查询。即使您使用此方法检索实体类型,返回数据也不会被数据库上下文跟踪。 • 使用Database.ExecuteSqlCommand进行非查询命令。
调用返回实体的查询:
public async Task<ActionResult> Details(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    // Commenting out original code to show how to use a raw SQL query.
    //Department department = await db.Departments.FindAsync(id);

    // Create and execute raw SQL query.
    string query = "SELECT * FROM Department WHERE DepartmentID = @p0";
    Department department = await db.Departments.SqlQuery(query, id).SingleOrDefaultAsync();

    if (department == null)
    {
        return HttpNotFound();
    }
    return View(department);
}
调用返回其他类型对象的查询:
public ActionResult About()
{
    //Commenting out LINQ to show how to do the same thing in SQL.
    //IQueryable<EnrollmentDateGroup> = from student in db.Students
    //           group student by student.EnrollmentDate into dateGroup
    //           select new EnrollmentDateGroup()
    //           {
    //               EnrollmentDate = dateGroup.Key,
    //               StudentCount = dateGroup.Count()
    //           };

    // SQL version of the above LINQ code.
    string query = "SELECT EnrollmentDate, COUNT(*) AS StudentCount "
        + "FROM Person "
        + "WHERE Discriminator = 'Student' "
        + "GROUP BY EnrollmentDate";
    IEnumerable<EnrollmentDateGroup> data = db.Database.SqlQuery<EnrollmentDateGroup>(query);

    return View(data.ToList());
}
调用更新查询:
[HttpPost]
public ActionResult UpdateCourseCredits(int? credit)
{
    if (credit != null)
    {
        ViewBag.RowsAffected = db.Database.ExecuteSqlCommand(
            "UPDATE Course SET Credits = Credits * {0}", credit);
    }
    return View();
}

欲了解更多信息,请查看MVC 5 Web应用程序的高级Entity Framework 6场景(12/12)


你的意思是只有Code First API提供这个功能,还是你的方法也可以应用于Database First方法? - Dr. Mian
不,即使您不使用Code-First,也可以借助EF使用此功能。 - Murat Yıldız
@MuratYıldız 这个回复应该被标记为“答案”。非常感谢您提供了非常详细的信息和最后的信息链接。由于我的背景也是“数据库优先方法”,所以我在工作中得到了巨大的帮助。 - nam
@nam 不客气,我很高兴它对你有帮助 :) - Murat Yıldız
@nam 还请不要忘记给我点赞,如果我的回答对您有帮助的话 ;) - Murat Yıldız
@MuratYıldız 当然,你应该得到它。我刚刚做了这件事。感谢您帮助读者(像我一样)理解您的回答。 - nam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接