zoukankan      html  css  js  c++  java
  • Entity Framework 4 in Action读书笔记——第四章:使用LINQ to Entities查询:执行手动查询

    4.8 执行手动查询

    有很多原因决定你会手动写查询。或许由EF生成的SQL太慢,又或许执行起来浪费了太多资源。另一种情况可能是当你动态生成一个如此复杂的查询,创建SQL代码比使用LINQ to Entities简单。

    在这种情况下,你自己可以使用ObjectContext类的ExecuteStoreQuery<T>创建一个SQL命令。它允许你发出任意的查询并将查询结果映射到类。它的使用如下:

    var details = ctx.ExecuteStoreQuery<OrderDetail>("Select * from OrderDetail");

    就是这么简单。查询被执行,列自动映射到实体。关于映射阶段有一个小小的提示:它绕过了EDM,而是使用另外一种基于属性-列名匹配的机制。这一行为如图:

    image

    这个映射解决方案的有一定的局限性:

    1.如果一个属性跟相应的列名称不同,映射就不会执行并抛出异常。你可以很容易的通过在查询中使用AS SQL子句重命名列解决这个问题。
    2.不能映射到有复杂属性的实体,因为没有办法将复杂属性内的名称和列进行匹配。

    当然,你可以映射返回的数据到任何类型的类,不仅仅是那些定义在EDM中的。假设,你创建了一个类OrderDetailProjection,有Quantity,UnitPrice和Discount属性。你可以写一个查询,从OrderDetail表中取出Quantity, UnitPrice和 Discount列,并将结果映射到OrderDetailProjection。

    public class OrderDetailProjection
    {
        public int Quantity { get; set; }
        public decimal UnitPrice { get; set; }
        public decimal Discount { get; set; }
    }
    var details = ctx.ExecuteStoreQuery<OrderDetailProjection>
                 ("Select quantity, unitprice, discount from OrderDetail");

    注意:

    通过ExecuteStoreQuery<T>,你也可以启动存储过程。但是我们不建议这样做,因为EF本身就支持存储过程并且提供了比ExecuteStoreQuery<T>更多的选项。

    如果查询带有参数,你可以使用ExecuteStoreQuery<T>的重载方法,它接受参数列表。这可能会非常棘手,所以让我们看一看。

    4.8.1 带参数的查询

    当初EF团队设计如何传递参数时,有很多的选择。通过选择,现在有两种操作参数的方式。

    1.使用带有编号列表,跟String.Format方法一样。
    2.使用ADO.NET语法

    下面,我们详细看一下这两种方式。

    使用带编号的列表

    这是最简单的办法。在SQL查询中,将数字放在花括号中代表参数。然后,你在方法的第二个参数中传递参数。参数既可以是简单的数值也可以是DbParameter类的实例。这里有一些建议,要牢记:

    1.如果你使用DbParameter实例,你必须使用与数据库Provider相应的具体类型。例如,如果对SQL Server就必须使用SqlParameter,对OLE DB就必须使用OleDbParameter。如果你使用其他的实例,在运行时会得到InvalidCastException。

    2.如果你有多个参数,你不能混用DbParameter实例和纯值。你必须选择其一。否则,在运行时会得到InvalidOperationException。

    3.如果你使用简单的数值作为参数,它们传过来的顺序必须和它们在查询中的顺序一样。

    使用简单数值传递参数

    var names = ctx.ExecuteStoreQuery<string>
        ("SELECT name FROM company WHERE shippingcity = {0} and billingcity = {1}", "New York", "Seattle");

    使用SqlParameter传递参数

    var p0 = new SqlParameter("p0", DbType.String) { Value = "New York" };
    var p1 = new SqlParameter("p1", DbType.String) { Value = "Seattle" };
    var names = ctx.ExecuteStoreQuery<string>("SELECT name FROM company WHERE shippingcity = {0} and billingcity = {1}", p0, p1);

    正如你所见,这里没有什么特别困难的。只要注意我们前面提到的陷阱即可。

    注意:

    即使此语法可能会导致你认为可以通过SQL注入攻击的影响,但绝对不是这种情况。参数往往作为安全的方式传递给数据库。

    现在,让我们继续谈谈使用传统的参数

    使用传统的参数

    通过经典的ADO.NET写查询时,你通常写这样的东西表达参数:

    SELECT * FROM table WHERE id = @id

    这种语法对SQL Server provider是有效的。如果你使用OLE DB provider,你必须问号(?)代替@paramname。

    这种方法使用ExecuteStoreQuery<T>方法仍然完全有效。不是将数字放在花括号中,而是放置参数。其他都一样。参数的值仍然可以作为简单数值或参数传递过来。

    使用简单数值传递参数

    var names = ctx.ExecuteStoreQuery<string>
                ("SELECT name FROM company WHERE shippingcity = @p0 and billingcity = @p1",
                "New York", "Seattle");

    使用SqlParameter传递参数

    var p0 = new SqlParameter("p0", DbType.String) { Value = "New York" };
    var p1 = new SqlParameter("p1", DbType.String) { Value = "Seattle" };
    var names = ctx.ExecuteStoreQuery<string>
    ("SELECT name FROM company WHERE shippingcity = @p0 and billingcity = @p1", p0, p1);
    如果将这段代码和前面的代码比较,你会发现只是SQL代码中参数声明发生了改变。剩下的仍然是相同的,也就是说,没有更多的东西需要学习。

    到目前为止,我们已经介绍了如何编写功能强大的查询。现在,我们换个角度思考:你有多少相关的实体需要查询?是直接检索出所有相关的实体,还是根据代码需要。这显然是一个获取(fetching)问题,它几乎独立与你写的任何查询。

  • 相关阅读:
    Android ELF文件格式
    AWS发布架构师认证的专业解决方案
    python django模型内部类meta详细解释
    SQL_substr功能测试
    猫学习IOS(四)UI半小时就搞定Tom猫
    使用jquery点击一个实现button或连接,进行以下div显示,在点击隐藏
    hdu2852--KiKi&#39;s K-Number(段树,求第一k的数量)
    信息安全官谁:逼近的挑战,你准备好了吗?
    VS2010使整个过程说明了安装包
    进程的创建与可执行程序的加载
  • 原文地址:https://www.cnblogs.com/nianming/p/2179238.html
Copyright © 2011-2022 走看看