详情介绍
LINQ TO SQL是一种包含在.NET Framework 3.5 版中的 O/RM 组件(对象关系映射),O/RM 允许你使用 .NET 的类来对关系数据库进行建模。提供了对事务、视图、存储过程的完全支持。它同样为集成数据校验和业务层逻辑到你的数据模型中提供了一种简单的实现方式。
LINQ to SQL:如何直接执行SQL语句1、ExecuteQuery方法
看命名,我们很容易联想到ADO.NET里熟悉的Command的ExecuteNonQuery方法,但是VS的智能提示告诉我们这个方法返回的是一个泛型集合,应该“所思非所得”。下面通过一个简单方法,验证我们的猜想(设计可以参考这一篇):
///
<summary>
/// 直接执行sql语句,获取总人数
/// </summary>
/// <returns></returns>
public int GetTotalCount()
{
string strSql = "SELECT COUNT(0) FROM Person(NOLOCK)";
var query = dataContext.ExecuteQuery<int>(strSql);
int result = query.First<int>();
Console.WriteLine();
Console.WriteLine("total count:{0}", result);
return result;
}
调试的时候,通过IntelliTrace跟踪到:
毫无疑问,上面的图片说明最初的想法是不正确的,”ADO.NET:执行Reader…”云云,让我们更加坚信它实际执行的应该是ExecuteReader方法。当然最简单的方法是直接查看它的方法说明:
// 摘要:
// 直接对数据库执行 SQL 查询并返回对象。
//
// 参数:
// query:
// 要执行的 SQL 查询。
//
// parameters:
// 要传递给命令的参数数组。注意下面的行为:如果数组中的对象的数目小于命令字符串中已标识的最大数,则会引发异常。如果数组包含未在命令字符串中引用的对象,则不会引发异常。如果某参数为
// null,则该参数会转换为 DBNull.Value。
//
// 类型参数:
// TResult:
// 返回的集合中的元素的类型。
//
// 返回结果:
//
由查询返回的对象的集合。
public IEnumerable<TResult> ExecuteQuery<TResult>(string query, params object[] parameters); ExecuteQuery
方法还有一个非泛型方法:
//
// 摘要:
// 直接对数据库执行 SQL 查询。
//
// 参数:
// elementType:
//
要返回的 System.Collections.Generic.IEnumerable<T> 的类型。使查询结果中的列与对象中的字段或属性相匹配的算法如下所示:如果字段或属性映射到特定列名称,则结果集中应包含该列名称。如果未映射字段或属性,则结果集中应包含其名称与该字段或属性相同的列。通过先查找区分大小写的匹配来执行比较。如果未找到匹配项,则会继续搜索不区分大小写的匹配项。如果同时满足下列所有条件,则该查询应当返回(除延迟加载的对象外的)对象的所有跟踪的字段和属性:T
// 是由 System.Data.Linq.DataContext 显式跟踪的实体。System.Data.Linq.DataContext.ObjectTrackingEnabled
// 为 true。实体具有主键。否则会引发异常。
//
// query:
// 要执行的 SQL 查询。
//
// parameters:
// 要传递给命令的参数数组。注意下面的行为:如果数组中的对象的数目小于命令字符串中已标识的最大数,则会引发异常。如果数组包含未在命令字符串中引用的对象,则不会引发异常。如果某参数为
// null,则该参数会转换为 DBNull.Value。
//
// 返回结果:
//
由查询返回的对象的 System.Collections.Generic.IEnumerable<T> 集合。
public IEnumerable ExecuteQuery(Type elementType, string query, params object[] parameters);
看它的参数需要多传递一个elementType,明显不如泛型方法简洁。
2、ExecuteCommand方法
同样道理,这个方法立刻让我们联想到(世界没有联想,生活将会怎样?),联想到,等等,不知联想到什么。然后我们看一下方法使用说明:
//
// 摘要:
// 直接对数据库执行 SQL 命令。
//
// 参数:
// command:
// 要执行的 SQL 命令。
//
// parameters:
// 要传递给命令的参数数组。注意下面的行为:如果数组中的对象的数目小于命令字符串中已标识的最大数,则会引发异常。如果数组包含未在命令字符串中引用的对象,则不会引发异常。如果任一参数为
// null,则该参数会转换为 DBNull.Value。
//
// 返回结果:
//
一个 int,表示所执行命令修改的行数。
public int ExecuteCommand(string command, params object[] parameters); 到这里,看它的返回类型为int,表示执行命令修改的行数,这次很容易想到ExecuteNonQuery方法。对不对呢?通过下面的代码证明我们的设想:
/// <summary>
/// 直接执行sql语句 根据用户Id更新体重
/// </summary>
/// <param name="id">用户Id</param>
/// <param name="destWeight">更新后的体重</param>
/// <returns></returns>
public int ModifyWeightById(int id, double destWeight)
{
string strSql = string.Format("UPDATE Person SET Weight={0} WHERE Id={1}", destWeight, id);
int result = dataContext.ExecuteCommand(strSql);
Console.WriteLine();
Console.WriteLine("affect num:{0}", result);
return result;
}
调试过程中,通过IntelliTrace可以很清楚地捕获:

“ADO.NET:执行NonQuery…”基本可以断言我们的设想是正确的。
3、防止sql注入
1和2中,执行sql语句的两个方法都有一个params 类型的参数,我们又会想到ADO.NET非常重要的sql语句的参数化防止sql注入问题。下面通过一个方法,看看linq2sql可不可以防止sql注入。
(1)、直接执行拼接的sql语句(有风险)
/// <summary>
/// 直接执行sql语句 根据用户Id更新FirstName
/// </summary>
/// <param name="id">用户Id</param>
/// <param name="destName">更新后的FirstName</param>
/// <returns></returns>
public int ModifyNameById(int id, string destName)
{
string strSql = string.Format("UPDATE Person SET FirstName='{0}' WHERE Id={1}", destName, id);//这么拼接有风险
int result = dataContext.ExecuteCommand(strSql);
Console.WriteLine();
Console.WriteLine("affect num:{0}", result);
return result;
}
然后,在客户端这样调用这个方法:
int result = ServiceFactory.CreatePersonService().ModifyNameById(10, "'Anders'");//更新id为10的人的FirstName
运行的时候,直接抛出异常,提示“Anders”附近有语法错误。毫无疑问,它执行的sql语句:
UPDATE Person SET FirstName=''Anders'' WHERE Id=10 是不能通过的,同时证明了string.format函数不能有效防止sql注入。
(2)、直接通过linq方法的参数传递,结果如何呢?
改进(1)的传参方法:
/// <summary>
/// 直接执行sql语句 根据用户Id更新FirstName
/// </summary>
/// <param name="id">用户Id</param>
/// <param name="destName">更新后的FirstName</param>
/// <returns></returns> public int ModifyNameById(int id, string destName)
{
//string strSql = string.Format("UPDATE Person SET FirstName='{0}' WHERE Id={1}", destName, id);//这么拼接有风险
//int result = dataContext.ExecuteCommand(strSql);
string strSql = "UPDATE Person SET FirstName={0} WHERE Id={1}";
int result = dataContext.ExecuteCommand(strSql, new object[] { destName, id });
Console.WriteLine();
Console.WriteLine("affect num:{0}", result);
return result;
}
再次通过如下的方式调用:
int result = ServiceFactory.CreatePersonService().ModifyNameById(10, "'Anders'");//更新id为10的人的FirstName 这一次运行正常吗?经测试,真的真的是真的正常,终于可以长松一口气了。查看数据库,Id为10的那一条记录的FirstName结果改变成了“'Anders'”(带单引号),明白ADO.NET工作原理的都知道这个一点也不神奇,不是吗?
对比(1)和(2),我们发现还是用linq2sql的源生方法传参比较好,通过拼接sql应该尽量避免。
到这里,可能你会认为上面1、2、3全是废话,知道怎么用不就行了嘛?!其实很长一部分时间我也是这么想这么做的。工作久了,早就习惯了不求甚解,现在看书,看园子里高手的博客,多多少少会有点反思。
4、思考
ADO.NET中比较常用的ExecuteScalar方法,在linq2sql应该怎么实现呢?您尝试使用过了吗?
下载地址
人气书籍
下载声明
☉ 解压密码:www.jb51.net 就是本站主域名,希望大家看清楚,[ 分享码的获取方法 ]可以参考这篇文章
☉ 推荐使用 [ 迅雷 ] 下载,使用 [ WinRAR v5 ] 以上版本解压本站软件。
☉ 如果这个软件总是不能下载的请在评论中留言,我们会尽快修复,谢谢!
☉ 下载本站资源,如果服务器暂不能下载请过一段时间重试!或者多试试几个下载地址
☉ 如果遇到什么问题,请评论留言,我们定会解决问题,谢谢大家支持!
☉ 本站提供的一些商业软件是供学习研究之用,如用于商业用途,请购买正版。
☉ 本站提供的LINQ to SQL语法及实例大全 中文PDF版资源来源互联网,版权归该下载资源的合法拥有者所有。













![MongoDB大数据处理权威指南(第3版) 中文pdf扫描版[48MB]](http://img.jbzj.com/do/uploads/litimg/190912/1H1252N0G.jpg)
![数据库云平台理论与实践 中文pdf扫描版[526MB]](http://img.jbzj.com/file_images/article/201911/2019115170518226.jpg)
![MongoDB游记之轻松入门到进阶 中文pdf扫描版[299MB]](http://img.jbzj.com/file_images/article/201911/2019116170058186.jpg)
![DB2从入门到精通 中文pdf扫描版[439MB]](http://img.jbzj.com/file_images/article/201912/2019124163936188.jpg)



![数据库系统概论 第四版 (王珊、萨师煊) PDF 扫描版[10M] 数据库系统概论 第四版 (王珊、萨师煊) PDF 扫描版[10M]](http://img.jbzj.com/do/uploads/litimg/130813/0939502241T.jpg)
![数据挖掘导论(完整版) PDF扫描版[61MB] 数据挖掘导论(完整版) PDF扫描版[61MB]](http://img.jbzj.com/do/uploads/litimg/140607/16453RR1c.png)

![大规模分布式系统架构与设计实战 PDF扫描版[42MB] 大规模分布式系统架构与设计实战 PDF扫描版[42MB]](http://img.jbzj.com/do/uploads/litimg/150202/15223RY927.jpg)
![Redis入门指南(李子骅) PDF扫描版[3M] Redis入门指南(李子骅) PDF扫描版[3M]](http://img.jbzj.com/do/uploads/litimg/140529/1F60RT136.png)
![中文版Access 2016宝典(第8版) 完整pdf扫描版[163MB] 中文版Access 2016宝典(第8版) 完整pdf扫描版[163MB]](http://img.jbzj.com/do/uploads/litimg/180224/1K4392N216.jpg)

![Redis实战 (Josiah L. Carlson ) 完整中文pdf扫描版[61MB] Redis实战 (Josiah L. Carlson ) 完整中文pdf扫描版[61MB]](http://img.jbzj.com/do/uploads/litimg/170622/1635042N2F.jpg)
![大话数据库(邹茂扬) PDF 高清扫描版[549M] 大话数据库(邹茂扬) PDF 高清扫描版[549M]](http://img.jbzj.com/do/uploads/litimg/140114/15121522S02.jpg)