zoukankan      html  css  js  c++  java
  • Entity Framework 4.0 recipes 读书笔记2 ExecuteStoreQuery()

    写在之前:我想通过refector 反编译一下system.data.entity.dll(4.0 version),发现反编译出来的只有属性申明和方法声明,里面一句代码都没有,真是火大啊,试了几个.net4.0的其它dll同样也是如此,并且我的机器上的refector是最新版的,后来我觉得可能是dll的路径不对,我引用的是C:Program FilesReference AssembliesMicrosoftFramework.NETFrameworkv4.0ProfileClientSystem.Data.Entity.dll,后来查找才知道,正确的路径是C:WindowsMicrosoft.NETFrameworkv4.0.30319System.Data.Entity.dll。不过很奇怪的是这个路径下C:Program FilesReference AssembliesMicrosoftFramework.NETFrameworkv3.5ProfileClientSystem.Data.Entity.dll反编译居然不正常。

    对一个entity data model进行查询的方式除了用linq to entity,linq to object,esq,还可以用sql ,store procedure(我有做写过blog,借助EFExtension和EntityClient来实现).不过在EF1中使用sql,procedure返回entity 是比较麻烦的。不过在EF4中对于使用sql ,store procedure返回entity就方便多了,因为不用再去调用EntityClient了,因为objectcontext提供了ExecuteStoreQuery<TElement>(),所以还是说具体的情况:

    1.Executing SQL Statement:如果需要直接去数据库表查询,可直接使用object context的ExecuteStoreCommand()方法。

      假设数据库表payment (PaymentId,Amount,Vendor),对应entity data model有一个Payment对象,

    下面的代码片段是通过object context insert payment,记得在EF1.0的是时候完成这个操作需要借助EntityClient.

    9}IV~B}JBOU~JB9EJ0$ZF9U

    图1

    using (var context = new EFRecipesEntities())
               {
                   string sql = @"insert into Payment(Amount, Vendor)
                                  values (@Amount, @Vendor)";
                   var args = new DbParameter[] {
                       new SqlParameter { ParameterName = "Amount", Value = 99.97M},
                       new SqlParameter { ParameterName = "Vendor", Value="Ace Plumbing"}
                   };
                   int rowCount = context.ExecuteStoreCommand(sql, args);

                   args = new DbParameter[] {
                       new SqlParameter { ParameterName = "Amount", Value = 43.83M},
                       new SqlParameter { ParameterName = "Vendor", Value = "Joe's Trash Service"}
                   };
                   rowCount += context.ExecuteStoreCommand(sql, args);
                   Console.WriteLine("{0} rows inserted", rowCount.ToString());
               }

    ExecuteStoreCommand()返回一个int值,影响的行数。

    2.Returning Objects from a SQL Statement:通过sql查询返回object实体,这个在EF1.0我也做过练习,那时候是通过EFExtension来实现的:

    下面的例子

    using (var context = new EFRecipesEntities())
    {
    string sql = "select * from  Payment where Vendor= @vendor";
    var args = new DbParameter[] {
    new SqlParameter {ParameterName = "Vendor", Value = "ken"}};
    var students = context.ExecuteStoreQuery<Payment >(sql, args);
    }

    这是一个非常简单的例子,对于ExecuteStoreQuery()有有许多需要注意:

    1.sql = "select * from  Payment where Vendor= @vendor";之所以能写成select *是因为Payment对象的属性和表的字段命名完全一致,如果不一致的话,需要将表字段 取别名,别名需是对象映射的属性名称。

    2.如果sql语句返回的列少于(具体化)实体的属性的个数,那么EF在具体化的时候将抛出一个异常如下图,因此将需要缺少的列补上一些没有意义的值,以保证在具体乎的时候不会报错:eg 如图1,如果sql=”select PaymentId ,Amount from Payment ” 这样使用context.ExecuteStoreQuery<Payment >(sql, args);那么会报异常,因此需要将Vendor 列补上 。

    Q9DK}Q5$VY@76B887(WBK}3

    正确的sql=”select PaymentId ,Amount, null as Vendor from Payment”。

    3.如果sql 返回的列 多余具体化的实体属性的个数,那么EF将会忽视多出的列。

       如下的代码调试可以通过:多出的test列在具体化(materialization)的时候是会忽略掉的

         string sql = "select PaymentId, Amount,Vendor,null as test from Chapter3.Payment “;

         var students = context.ExecuteStoreQuery<Payment>(sql); ;
         Console.WriteLine("Payment...");

      
    4.如果是你返回的表是映射到几个继承关系的实体类上,那么返回的行需要具体化到几个实体上,EF是无法根据识别列来将返回的行具体化到相应的继承类型上去,这是EF会抛出一个运行时的exception

    M3YEQ{$KX7L_L2HSE4AZ}(S

    图1

    $EEP7O}KO%TM0LXP@HWEL21

       图2

    sing (var context = new EFRecipesEntities())
    {
        string sql = "select * from Employee";
        var employee = context.ExecuteStoreQuery<Employee>(sql);                  
    }

    如上图模型和代码,图2是异常信息。

    5.如果实体有complex Type属性,那么实体对象的实例是无法用ExecuteStoreQuery()来返回的,因为ExcuteStoreQuery()是无法返回一个complex Type的集合的.返回单个complex type是支持的,但是返回的实体对象里包含complex type就不支持。

    6.可以返回实体对象属性的子集,就是说如果对于Payment表,我们查询返回PaymentId和Amount字段,然后我们定义一个subPayment 实体包含PaymentId和Amount属性,然后使用ExcuteStoreQuery<subPayment>()

    3.Returning Objects from an Entity SQL Statement:通过esql返回实体对象. 这个和EF1.0没什么区别,可以去下载最新版的EF query sample

    4.setting a default value in a query 在查询中设置默认值:

       1.最简单的办法就是在实体的属性上设置默认值

       2.就是使用匿名实体,就像这样 var employees = from e in context.Employees select new {Name = e.Name, YearsWorked = e.YearsWorked ?? 0};

       3.通过sql语句,不过这需要借助DbDataRecord来实现,eg:string esql = @"select e.Name,case  when .YearsWorked is null then 0 else e.YearsWorked end as YearsWorked from Employees as e"; var employees = context.CreateQuery<DbDataRecord>(esql);

       4.对于linq to entity没有相应的方法。

  • 相关阅读:
    OA项目之分页
    OA项目之弹出层中再弹出层
    OA项目之导入
    OA项目之导出
    git使用6步走
    配置 Docker 镜像站
    Taro随笔
    byte(C# 参考)
    MySQL 笔记
    HTTP 错误代码
  • 原文地址:https://www.cnblogs.com/Alex80/p/7094345.html
Copyright © 2011-2022 走看看