便便代码人生

关注技术, 偶尔动动手

[原] Linq不能使用CLR Stored Procedure返回ISingleResult

Posted by bianbian on 2011-07-27 12:53


本文Tags: , ,

使用C#写CLR存储过程确实很方便。
不过遗憾的是,如果CLR里通过SqlContext.Pipe.Send()返回Select结果的话,并不能被Linq to SQL自动识别而返回ISingleResult的。(因为部署CLR存储过程实际产生的代码是不包含select语句的)
换句话说,所有CLR存储过程的返回值在Linq to SQL里都会被当成int。
解决办法:
1)如果该存储过程没有out的参数,比较好办:使用ExecuteQuery并EXEC 存储过程
如:
var query = DataContext.ExecuteQuery(“EXEC P_LoadUserWithTraining @trainingId={0}”, id).Single();
这种方法能取到结果,但是没有办法获得out参数。

2)如果该存储过程又有out的参数需要获得值,又返回select结果集的:
非常麻烦,只能部署CLR存储过程前,先手动在数据库里create procedure(同名,里面填上参数和select语句),
然后骗取Linq to SQL生成返回ISingleResult的代码,然后drop procedure,再部署CLR存储过程。
否则,即使把返回int的代码手动改成返回ISingleResult的,也会报错。我这里一直报 ArgumentOutOfRangeException
所以针对这种存储过程,最好还是T-SQL语句写。CLR的反而好麻烦。

标签: , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in C#, Database, Technology | 1 Comment »

[原]用PL/pgSQL写postgreSQL的存储过程

Posted by bianbian on 2006-10-27 01:40


本文Tags: , ,

今天学会了用 PL/pgSQL 写 postgreSQL 的存储过程,网上资料实在少得可怜,唯一能搜到的一些还是抄来抄去的;还是翻postgresql的文档吧,把今天解决的问题说一下吧,希望对其他人有帮助。
问题是这样的,有一张message表:
CREATE TABLE message
(
id int8 NOT NULL,
receiveuserid int8,
senduserid int8,
receivedelete bool DEFAULT false,
senddelete bool DEFAULT false,
……
CONSTRAINT usermessage_pkey PRIMARY KEY (id)
)
略去其他字段,senduserid是发信息的用户id,senddelete如为true则表示这条消息被发信人所删除;至于receive我就不用说了。一条信息只有被发信人和收信人都删除,才能真正从表里删除(这是显然的,否则收信人删了一条消息后,发信人的“发件箱”里就会找不到这条消息)。
所以删除消息(可能是多条消息)的时候要进行各种判断(是否是发信人?是否是收信人?是否真正删除?),用单条SQL语句完成这个工作显然有些困难(当然用循环嵌套select不考虑效率的话也是可以实现的),只好写存储过程了。
顺便介绍常用的PL/pgSQL结构和语法吧:

  • 结构
  • PL/pgSQL是一种块结构的语言,比较方便的是用pgAdmin III新建Function,填入一些参数就可以了。基本上是这样的:

    CREATE OR REPLACE FUNCTION 函数名(参数1,[整型 int4, 整型数组 _int4, ...])
    RETURNS 返回值类型 AS
    $BODY$
    DECLARE
    变量声明
    BEGIN
    函数体
    END;
    $BODY$
    LANGUAGE ‘plpgsql’ VOLATILE;

  • 变量类型
  • 除了postgresql内置的变量类型外,常用的还有 RECORD ,表示一条记录。

  • 赋值
  • 赋值和Pascal有点像:“变量 := 表达式;”
    有些奇怪的是连接字符串的是“||”,比如 sql := ‘SELECT * FROM’ || table || ‘WHERE …’;

  • 判断
  • 判断又和VB有些像:
    IF 条件 THEN

    ELSEIF 条件 THEN

    ELSE

    END IF;

  • 循环
  • 循环有好几种写法:
    WHILE expression LOOP
    statements
    END LOOP;
    还有常用的一种是:(从1循环到9可以写成FOR i IN 1..9 LOOP)
    FOR name IN [ REVERSE ] expression .. expression LOOP
    statements
    END LOOP;

  • 其他
  • 还有几个常用的函数:
    SELECT INTO record …; 表示将select的结果赋给record变量(RECORD类型)
    PERFORM query; 表示执行query并丢弃结果
    EXECUTE sql; 表示执行sql语句,这条可以动态执行sql语句(特别是由参数传入构造sql语句的时候特别有用)

最后,贴出解决上面这个问题的存储过程吧:

  1. CREATE OR REPLACE FUNCTION message_deletes(ids "varchar", userid int8)
  2.   RETURNS int4 AS
  3. $BODY$
  4. DECLARE
  5.   r RECORD;
  6.   del bool;
  7.   num int4 := 0;
  8.   sql "varchar";
  9. BEGIN
  10.   sql := 'select id,receiveuserid,senduserid,senddelete,receivedelete from message where id in (' || ids || ')';
  11.   FOR r IN EXECUTE sql LOOP
  12.     del := false;
  13.     IF r.receiveuserid=userid and r.senduserid=userid THEN
  14.       del := true;
  15.     ELSEIF r.receiveuserid=userid THEN
  16.       IF r.senddelete=false THEN
  17.         update message set receivedelete=true where id = r.id;
  18.       ELSE
  19.         del := true;
  20.       END IF;
  21.     ELSEIF r.senduserid=userid THEN
  22.       IF r.receivedelete=false THEN
  23.         update message set senddelete=true where id = r.id;
  24.       ELSE
  25.         del := true;
  26.       END IF;
  27.     END IF;
  28.     IF del THEN
  29.       delete from message where id = r.id;
  30.       num := num + 1;
  31.     END IF;
  32.   END LOOP;
  33.   return num;
  34. END;
  35. $BODY$
  36.   LANGUAGE 'plpgsql' VOLATILE;

测试使用:
postgres PL/pgSQL

标签: , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Database, Technology | 4 Comments »