封装一个数据库操作的类,如果类包含有多条SQL语句,Parameters参数该怎么写吗?

蜗牛学编程 2021-01-24 08:52:44
练习封装类时发现困难点:
为避免SQL注入攻击,要给SQL传参。如果仅是单条SQL语句没问题,直接加一个Parameters SQLParameter[]作为占位就可以。
但如果是多条SQL,每条SQL都要有不同的参数,那该怎么加这个Parameters吗?占位符只允许放一个Parameters,放在最后面。
不知道我有没有说清楚。
请老师们指点。

...全文
1391 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
Lvwl 2021-02-03
  • 打赏
  • 举报
回复
要是执行3条sql,你还得再写一个方法?4条5条、、、呢? 换个思路吧
正怒月神 2021-01-29
  • 打赏
  • 举报
回复
引用 14 楼 蜗牛学编程 的回复:
[quote=引用 13 楼 正怒月神 的回复:]我的建议是。。。 根本不需要封装,有多条sql语句的方法。。。 原因在于, 只是同一个方法,执行了2遍不同sql语句,仅此而已。 其次假设你拥有很复杂的逻辑,又不想在程序中完成,那就使用存储过程。
版主您好。 是这样一个情况,我写了一个系统,里面很多页面。然后要求数据在页面之间来回修改后传送,而传送完后要写一条记录,记录下修改了什么内容。为了方便,我就想封装成一个类,不想拆开成为两个。(拆开两个就没这个问题,但这样要多写一次方法,而且数据库也会多一次打开关闭,频繁操作,会不会影响效率?)[/quote] 方法多种多样, 与其把你的sqlhelper改的不这么简单通用, 还不如 1 将新增和记录,两个动作在逻辑层去聚合。 #15 已经说了很多种方法,就不赘述了。 2 将改记录动作,通过aop去实现,作为一个注解。 在需要的方法上,使用注解就能而不会影响到业务本身。
wanghui0380 2021-01-29
  • 打赏
  • 举报
回复
思维有很多种,聚合是一类。 通知也是一类。还是前面说的如果说你单纯就是走一步看一步,那就把自己给困死了。 我们来看几类应用 1.注册用户-------------------------------积分+50 2.荣誉系统-----------完成任务------------荣誉值+1,荣誉称号xxx 3.推荐系统---------------点击商品-------------生成推荐系统 如果说就走一步是一步。那么我说注册用户的积分+50,荣誉值+1,荣誉称号“超级新人”,生成新人推荐任务,这几个同时来,你打算怎么写sql?? 这时候还是各做各的,使用“中间件”订阅 “用户系统/新人注册”topic了。 所以当你说你的老板要求你在修改数据的时候记录一下谁修改的,那么你其实要做的事情是 给个“日志记录/db修改操作”topic通知,让日志系统去完成。而不是这里弄个sql1,sql2
xiaoxiangqing 2021-01-29
  • 打赏
  • 举报
回复
占位符只允许放一个Parameters
wanghui0380 2021-01-29
  • 打赏
  • 举报
回复
引用 14 楼 蜗牛学编程 的回复:
[quote=引用 13 楼 正怒月神 的回复:]我的建议是。。。 根本不需要封装,有多条sql语句的方法。。。 原因在于, 只是同一个方法,执行了2遍不同sql语句,仅此而已。 其次假设你拥有很复杂的逻辑,又不想在程序中完成,那就使用存储过程。
版主您好。 是这样一个情况,我写了一个系统,里面很多页面。然后要求数据在页面之间来回修改后传送,而传送完后要写一条记录,记录下修改了什么内容。为了方便,我就想封装成一个类,不想拆开成为两个。(拆开两个就没这个问题,但这样要多写一次方法,而且数据库也会多一次打开关闭,频繁操作,会不会影响效率?)[/quote] 这样回答很好,但是我们说请回答“封装的意义”,你为啥要封装,仅仅是为了你说的这个功能?仅仅是说,我嫌不好看,要多敲几句代码 封装是为了复用。那么sql1,sql2,如果说要复用为啥不是sql1,sql2,sql3,sqlN,你说对吧。 当然我们不是更那几个5年兄弟一样说这是批评你,我们只是告诉你如果要走这条路那就需要多看几步,单单走一步看一步的话其实坑的是自己。因为你就只看了一步,明天你领导说,写完sql2,在给我做个统计,你又打算怎么封装 所以他最终的事情结果就说版主告诉你的,别做走一步看一步的封装。这种封装看着很好,但是给自己挖坑 想不坑自己我们一次只做一件事情,只是用聚合类的手段聚合 比如pipeline,职责链。当然他叫什么不重要,重要的聚合的思维。 为了体现思维,我就特地不叫他为职责链。我就叫他批处理如何 批处理 批处理任务=new批处理() .add任务(new sql任务(sql1,参数)) .add任务(new sql任务(sql2,参数)) 任务上下文 =new 任务上下文() 批处理任务.执行(任务上下文 ) 这样就好,一个任务就是一个任务,我们只是聚合他,而不是改变他
wanghui0380 2021-01-29
  • 打赏
  • 举报
回复
同样的设计思路 Service.AddSocpe<数据库操作辅助类>() //本次Request有效 Service.Add<全局日志记录>() 这种设计依旧可以把 -------------------------------------------------------------- 在换个表现AOP [日志记录拦截属性] xxxAction() 还是可以接受把
wanghui0380 2021-01-29
  • 打赏
  • 举报
回复
实际项目不拘泥形式,只要你们不跟着那个园子走。能真正理解设计意图,就会发现那个园子的路太偏(包括动则各种这个vs那个,各种string血案,动则DDD典范ABP,动则一次连接数据库,多次连接数据库的无端折腾,动则改进系统性能的XXX建议) 回你的问题,我们来看看如果你理解设计意图了,你就算不跟着他们走,你的问题也不成为问题 Service.AddSocpe<数据库操作辅助类>() //本次Request有效 Service.AddTransient<聚合操作任务A>() //永远瞬时,当然我这里不过渡设计,仅仅表现微软这套框架的设计意图,所以把聚合操作任务直接放在全局ServiceCollection里 Service.AddTransient<聚合操作任务B>() class 聚合操作任务A(数据库操作辅助类) { 执行() { 数据库操作辅助类.sqlExecute() } } class XXXControl(聚合操作任务A,聚合操作任务B) { xxxxAction() { 聚合操作任务A.执行() 聚合操作任务B.执行() } } 我们做什么了?我们什么都没做,完完全全的netcore的标准执行代码。看他怎么样? 需要多余的操作么?不需要 Socpe的数据库操作类,在同一个Reqeust下他回实例几次?1次,所以你操心的问题,原本就不存在。 而写法上,你该怎么写就怎么写,不需要纠结那个园子里越走越窄的死胡同
code_long 2021-01-29
  • 打赏
  • 举报
回复
引用 19 楼 code_long 的回复:

    public class SqlHelper
    {
        public string GetSqlConnection()
        {
            return "";
        }

        public void Operate(params SqlParameterModel[] models)
        {
            using (SqlConnection con = new SqlConnection(this.GetSqlConnection()))
            {
                foreach (var item in models)
                {
                    using (SqlCommand cmd = new SqlCommand(item.StrSql, con))
                    {
                        cmd.Parameters.AddRange(item.Prm);
                        cmd.ExecuteNonQuery();
                    }
                }
            }
        }
    }

    public class SqlParameterModel
    {
        public SqlParameterModel()
        {
            StrSql = string.Empty;
        }
        public string StrSql { get; set; }
        public SqlParameter[] Prm { get; set; }
    }
执行的SQl,可以再加上SqlTransaction
code_long 2021-01-29
  • 打赏
  • 举报
回复

    public class SqlHelper
    {
        public string GetSqlConnection()
        {
            return "";
        }

        public void Operate(params SqlParameterModel[] models)
        {
            using (SqlConnection con = new SqlConnection(this.GetSqlConnection()))
            {
                foreach (var item in models)
                {
                    using (SqlCommand cmd = new SqlCommand(item.StrSql, con))
                    {
                        cmd.Parameters.AddRange(item.Prm);
                        cmd.ExecuteNonQuery();
                    }
                }
            }
        }
    }

    public class SqlParameterModel
    {
        public SqlParameterModel()
        {
            StrSql = string.Empty;
        }
        public string StrSql { get; set; }
        public SqlParameter[] Prm { get; set; }
    }
正怒月神 2021-01-28
  • 打赏
  • 举报
回复
我的建议是。。。 根本不需要封装,有多条sql语句的方法。。。 原因在于, 只是同一个方法,执行了2遍不同sql语句,仅此而已。 其次假设你拥有很复杂的逻辑,又不想在程序中完成,那就使用存储过程。
蜗牛学编程 2021-01-28
  • 打赏
  • 举报
回复
引用 13 楼 正怒月神 的回复:
我的建议是。。。 根本不需要封装,有多条sql语句的方法。。。 原因在于, 只是同一个方法,执行了2遍不同sql语句,仅此而已。 其次假设你拥有很复杂的逻辑,又不想在程序中完成,那就使用存储过程。
版主您好。 是这样一个情况,我写了一个系统,里面很多页面。然后要求数据在页面之间来回修改后传送,而传送完后要写一条记录,记录下修改了什么内容。为了方便,我就想封装成一个类,不想拆开成为两个。(拆开两个就没这个问题,但这样要多写一次方法,而且数据库也会多一次打开关闭,频繁操作,会不会影响效率?)
白衣如花 2021-01-27
  • 打赏
  • 举报
回复
引用 7 楼 蜗牛学编程 的回复:
[quote=引用 5 楼 白衣如花 的回复:]用list,别用params


public void operate(List<string> sqls, List<SqlParameter[]> param)

你好,可以帮忙完整的写一下这段代码吗?没用过list<>的方式,代码正文不知道该怎么写
[/quote]你试试走出舒适区,查一下List怎么用,认识一下尖括号

语法和逻辑和数组类似,很好理解,不难

如果学过数据结构就知道这是个线性表,而且很可能是链表

不查不学怎么进步呢
蜗牛学编程 2021-01-27
  • 打赏
  • 举报
回复
引用 10 楼 锤子馆长 的回复:
[quote=引用 楼主 蜗牛学编程 的回复:]练习封装类时发现困难点: 为避免SQL注入攻击,要给SQL传参。如果仅是单条SQL语句没问题,直接加一个Parameters SQLParameter[]作为占位就可以。 但如果是多条SQL,每条SQL都要有不同的参数,那该怎么加这个Parameters吗?占位符只允许放一个Parameters,放在最后面。 不知道我有没有说清楚。 请老师们指点。
为啥2个SQL语句 合并成一个字符串 统一执行 就可以了[/quote] 因为两条SQL语句是有不同作用的啊。譬如说我先把一组数据copy转移到另外一个表格,然后再在原表格上进行删除。这样没办法合并成一个字符串呀
datafansbj 2021-01-27
  • 打赏
  • 举报
回复
引用 6 楼 蜗牛学编程 的回复:
[quote=引用 4 楼 datafansbj 的回复:]

我两条SQL都有参数啊。用一条第二条参数就会报错,提示必须声明变量[/quote]

你需要把两条 SQL 的参数整合到一个数组里作为参数传递进来,两条 SQL 的参数可以是一样的,类似如下:
private void operate(string sql1, string sql2, params SqlParameter[] prm)
{
......
c1.Parameters.AddRange(prm);
c2.Parameters.AddRange(prm);
......
}
wllllll 2021-01-27
  • 打赏
  • 举报
回复
我的类,给你参考。类似于ASP的写法。又加入了NET的特性。其实在后台还有SQL缓存模块。
锤子馆长 2021-01-27
  • 打赏
  • 举报
回复
引用 楼主 蜗牛学编程 的回复:
练习封装类时发现困难点: 为避免SQL注入攻击,要给SQL传参。如果仅是单条SQL语句没问题,直接加一个Parameters SQLParameter[]作为占位就可以。 但如果是多条SQL,每条SQL都要有不同的参数,那该怎么加这个Parameters吗?占位符只允许放一个Parameters,放在最后面。 不知道我有没有说清楚。 请老师们指点。
为啥2个SQL语句 合并成一个字符串 统一执行 就可以了
蜗牛学编程 2021-01-26
  • 打赏
  • 举报
回复
引用 5 楼 白衣如花 的回复:
用list,别用params

public void operate(List<string> sqls, List<SqlParameter[]> param)
你好,可以帮忙完整的写一下这段代码吗?没用过list<>的方式,代码正文不知道该怎么写
蜗牛学编程 2021-01-26
  • 打赏
  • 举报
回复
引用 4 楼 datafansbj 的回复:
我两条SQL都有参数啊。用一条第二条参数就会报错,提示必须声明变量
白衣如花 2021-01-26
  • 打赏
  • 举报
回复
用list,别用params


public void operate(List<string> sqls, List<SqlParameter[]> param)
datafansbj 2021-01-26
  • 打赏
  • 举报
回复
加载更多回复(3)
SqlHelper源码及使用实例下载 SqlHelper 实现详细信息 SqlHelper 用于通过一组静态方法来封装数据访问功能。该不能被继承或实例化,因此将其声明为包含专用构造函数的不可继承。 在 SqlHelper 中实现的每种方法都提供了一组一致的重载。这提供了一种很好的使用 SqlHelper 来执行命令的模式,同时为开发人员选择访问数据的方式提供了必要的灵活性。每种方法的重载都支持不同的方法参数,因此开发人员可以确定传递连接、事务和参数信息的方式。在 SqlHelper 中实现的方法包括: ExecuteNonQuery。此方法用于执行不返回任何行或值的命令。这些命令通常用于执行数据库更新,但也可用于返回存储过程的输出参数。 ExecuteReader。此方法用于返回 SqlDataReader 对象,该对象包含由某一命令返回的结果集。 ExecuteDataset。此方法返回 DataSet 对象,该对象包含由某一命令返回的结果集。 ExecuteScalar。此方法返回一个值。该值始终是该命令返回的第一行的第一列。 ExecuteXmlReader。此方法返回 FOR XML 查询的 XML 片段。 除了这些公共方法外,SqlHelper 包含一些专用函数,用于管理参数和准备要执行的命令。不管客户端调用什么样的方法实现,所有命令都通过 SqlCommand 对象来执行。在 SqlCommand 对象能够被执行之前,所有参数都必须添加到 Parameters 集合中,并且必须正确设置 Connection、CommandType、CommandText 和 Transaction 属性。SqlHelper 中的专用函数主要用于提供一种一致的方式,以便向 SQL Server 数据库发出命令,而不考虑客户端应用程序调用的重载方法实现。SqlHelper 中的专用实用程序函数包括: SqlHelper是非常方便的数据库操作函数,功能强大,使用起来非常简单,免去很多复杂的数据库操作的代码,在多层应用及面向对象开发中都有很多应用 SqlHelper源码带有详细的说明,示例中有原始的示例Sql语句 主要包括以下操作: 简单SQL语句(ExcuteSql) 带参数的简单SQL语句(ExcuteSQLParm) 简单存储过程 (ExcuteProc) 带参数的存储过程(ExcuteProcParm) 只返回一个字段 (ExcuteScalar) 返回数据集(ExcuteReader) 数据库中有示例数据及存储过程updateTable\updateTableByParm,大家可以自行修改测试

110,545

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧