[英]How can I get output values into output parameters?
I am using C# in VS 2008 to retrieve data from a PostgreSQL stored procedure that has two input parameters and two output parameters. 我在VS 2008中使用C#从具有两个输入参数和两个输出参数的PostgreSQL存储过程中检索数据。 When I created the procedure, PostgreSQL told me that I had to specify that it returns a record.
创建该过程时,PostgreSQL告诉我必须指定它返回一条记录。
In VS2008, my first attempt to use the procedure involved creating an OdbcCommand
object of type CommandType.StoredProcedure
and giving it four parameters, two with direction of Input and two of direction Output. 在VS2008中,我首次尝试使用该过程涉及创建类型为
CommandType.StoredProcedure
的OdbcCommand
对象,并为其提供四个参数,两个参数为Input方向,两个参数为Output方向。 The command executed without error, first using ExecuteNonQuery()
and then using ExecuteReader()
, but the values of the output parameters were null. 执行该命令没有错误,首先使用
ExecuteNonQuery()
,然后使用ExecuteReader()
,但是输出参数的值为null。 I called the reader's GetValues()
function, and found that the result was a single object containing the string "{3,4}"
. 我调用了读者的
GetValues()
函数,发现结果是一个包含字符串"{3,4}"
的单个对象。
Then, following a suggestion from StackOverflow, I changed the command text to: {call closest_idle_cover(?, ?, ?, ?)} 然后,根据StackOverflow的建议,我将命令文本更改为:{call hidden_idle_cover(?,?,?,?)}
This also worked, and GetValues()
gave me an array of two objects of type int, one with 3 and the other with 4. This was quite a bit better, since I wouldn't have to parse a string. 这也起作用,并且
GetValues()
给我一个数组,其中包含两个类型为int的对象,一个对象为3,另一个对象为4。这要好很多,因为我不必解析字符串。 But the output parameters still have null values, and indeed, the command works just as well if I only pass in the two input parameters. 但是输出参数仍然具有空值,并且实际上,如果我仅传递两个输入参数,该命令也可以正常工作。
So, although I have a solution that works, I remain curious: How can I get the values into my output parameters? 因此,尽管我有一个可行的解决方案,但我仍然感到好奇:如何将这些值输入到输出参数中?
Here's the PostgreSQL stored procedure: 这是PostgreSQL存储过程:
CREATE OR REPLACE FUNCTION plant_genie.closest_idle_cover(IN int, IN int, OUT int, OUT int)
RETURNS record AS
$BODY$
DECLARE
current_x ALIAS FOR $1;
current_y ALIAS FOR $2;
target_x ALIAS FOR $3;
target_y ALIAS FOR $4;
coverLocations ic_storage_locations%rowtype;
BEGIN
target_x := 3;
target_y := 4;
SELECT INTO coverLocations *
FROM ic_storage_locations
WHERE inner_cover IS NOT NULL
ORDER BY sqrt(pow(current_x - ic_storage_locations.x_coordinate, 2) +
pow(current_y - ic_storage_locations.y_coordinate, 2))
LIMIT 1;
IF FOUND THEN
INSERT INTO op_messages (message) VALUES ('Found a cover location record.');
target_x := coverLocations.x_coordinate;
target_y := coverLocations.y_coordinate;
ELSE
INSERT INTO op_messages (message) VALUES ('Could not find a cover location record.');
END IF;
END;
$BODY$ LANGUAGE 'plpgsql' VOLATILE COST 100;
You are using OUT
parameters but then also a RETURNS record
clause, without having an explicit RETURN
statement in the body of the function. 您正在使用
OUT
参数,但同时使用RETURNS record
子句,而在函数主体中没有显式的RETURN
语句。 That combination does not work. 这种组合不起作用。 A more elegant solution than using
OUT
parameters is to define the output table format - it is more obvious what is going on: 比使用
OUT
参数更优雅的解决方案是定义输出表格式-发生的情况更加明显:
CREATE OR REPLACE FUNCTION plant_genie.closest_idle_cover(current_x int, current_y int)
RETURNS TABLE (target_x int, target_y int) AS $BODY$
DECLARE
coverLocations ic_storage_locations%rowtype;
BEGIN
SELECT INTO coverLocations *
FROM ic_storage_locations
WHERE inner_cover IS NOT NULL
ORDER BY pow(current_x - ic_storage_locations.x_coordinate, 2) +
pow(current_y - ic_storage_locations.y_coordinate, 2)
LIMIT 1;
IF FOUND THEN
INSERT INTO op_messages (message) VALUES ('Found a cover location record.');
RETURN QUERY SELECT coverLocations.x_coordinate, coverLocations.y_coordinate;
ELSE
INSERT INTO op_messages (message) VALUES ('Could not find a cover location record.');
END IF;
END; $BODY$ LANGUAGE 'plpgsql' STRICT;
So if you call this function you are returned a record if at least 1 ic_storage_location is not null: 因此,如果调用此函数,并且至少有1个ic_storage_location不为null,则会返回一条记录:
SELECT * FROM plant_genie.closest_idle_cover(1, 2);
You can deal with that in your C# code like you would any other data you pull out of the database. 您可以像使用其他任何从数据库中提取的数据一样,在C#代码中进行处理。
A few observations: 一些观察:
SQRT()
function call, which is computationally expensive. SQRT()
函数调用,这在计算上是昂贵的。 Just working with the squared sums has the same property of ordering records by distance from the current location. STRICT
because it requires values for both parameters to work properly. STRICT
因为它需要两个参数的值才能正常工作。 COST
values yourself, unless you really know what you are doing. COST
值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.