Levy.Net

它山之石,可以为错; 它山之石,可以攻玉
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Linq to SQL 之 返加Entity的某几列数据

Posted on 2008-06-16 18:05  LevyLiu  阅读(844)  评论(2)    收藏  举报
    我现在负责公司一个项目的框架设计,老板要用vs2008开发(老板比较喜欢MS的新技术),既然用vs2008,当然是用.Net Framework3.5里新的东西.Linq自然是被选中. 目前是用Linq to SQL实现一个轻量级的ORM. Linq to SQL的CRUD中,Delete功能很是BT,已用自己的方法实现了Delete操作了. 扯远了,现在来说一下主题.
     刚开始设计时,返回Entity数据都是返回所有的列,有的业务操作自然是不需要Entity的所有列,所以我想当然的这样写:
            var querys = from order in this.dataContext.Orders
                         
where order.CustomerID == customerId
                         select 
new Orders
                         
{
                             order.OrderID,
                             order.OrderDate,
                             order.ShipName
                         }
;
    谁知竟然报错,到网上查了,才知MS没有供对Entity只返回某几列的功能,要不是公司开着空调,我可能要晕死了.
    但不能不提供只返回Entity某几列的方法啊,这是性能优化的必备条件之一,只能通过间接方法来实现了.
    想到DataContext.ExecuteQuery()方法可以返回Entity,它接受sql语句,而DataContext.GetCommand()方法可以得到一个DbCommand对象,不就得到CommandText的sql语句吗? 
    而DataContext.GetCommand()方法的IQueryable参数不就是我们的查询表达式的结果吗?
    实现的方法:
        public IEnumerable<T> RetriveMultipleByQueryable1<T>(IQueryable query)
        
{
            DbCommand dc 
= this.dataContext.GetCommand(query);

            
object[] prms = new object[dc.Parameters.Count];
            
string sql = dc.CommandText;
            
for (int i = 0; i < dc.Parameters.Count; i++)
            
{
                sql 
= sql.Replace(dc.Parameters[i].ParameterName, "{" + i.ToString() + "}");
                prms[i] 
= dc.Parameters[i].Value;
            }


            IEnumerable
<T> result = this.dataContext.ExecuteQuery<T>(sql, prms);
            
return result; 
        }

    在这里,因为ExecuteQuery()的需要,要将DbCommand.CommandText的各参数名替换为占位符,比如说DbCommand.CommandText的值形如:
        "select .... from ... where field1=@p0 and field2=@p1"
    则要替换为:
        "select .... from ... where field1={0} and field2={1}"

    调用方法:
        public List<Orders> GetOrdersByCustomerId(string customerId)
        
{
            var querys 
= from order in this.dataContext.Orders
                         
where order.CustomerID == customerId
                         select 
new
                         
{
                             order.OrderID,
                             order.OrderDate,
                             order.ShipName
                         }
;
            IEnumerable
<Orders> result = this.RetriveMultipleByQueryable1<Orders>(querys);

            
return result.ToList();
        }

    在这里,用到了匿名类的技术,所以用var来声明。我们并不会去产生匿名类的实例,用它只是为了达到选择Entity某几列的目的。
    大功告成。

    总的来说,Linq to SQL是很强的,但缺点也不少,希望MS对其完善一些。