#.net #performance #oracle #dataset
#.net #Производительность #Oracle #набор данных
Вопрос:
Я нашел несколько вопросов / ответов на SOF о том, как запускать несколько запросов к Oracle (начальный конечный блок, анонимная хранимая процедура). Я хочу сделать практически то же самое, но я хочу, чтобы эти запросы заполняли несколько таблиц данных «за один раз»:
Итак, вместо нашего обычного: один запрос на DataTable like (это «псевдокод», а не рабочий пример!)
Odp.Fill(SomeQuery, SomeDataTable, SomeParameters);
Я хотел бы сделать что-то вроде
Odp.Fill(
new Query(SomeQuery, SomeDataTable, SomeParameters),
new Query(SomeQuery2, SomeDataTable2, SomeParameters),
...)
Комментарии:
1. Почему вы хотите использовать один вызов вместо нескольких? Это из-за простоты использования, ожидания значительного увеличения производительности, атомарного выполнения, обработки транзакций, обработки ошибок и т.д.?
2. > «ожидание (значительного) увеличения производительности» Реализация этого нового метода «BulkFill» также была бы хорошим моментом для добавления (пользовательский? т.е. Обработка ошибок нового запроса (sql, dt, customErrMsg)), уменьшение объема кода DAL, улучшение «читаемости» методов заполнения, …
Ответ №1:
Это только один из многих способов, которыми вы могли бы получить несколько таблиц в одном запросе.
PL / SQL
CREATE OR REPLACE PACKAGE getBldgRoom AS
/******************************************************************************
NAME: getBldgRoom
PURPOSE:
REVISIONS:
Ver Date Author Description
--------- ---------- --------------- ------------------------------------
1.0 2011-5-27 has986 1. Created this package.
******************************************************************************/
PROCEDURE getBldgRoom(rcBuildingData OUT SYS_REFCURSOR, rcRoomData OUT SYS_REFCURSOR);
END getBldgRoom;
/
CREATE OR REPLACE PACKAGE BODY GETBLDGROOM AS
PROCEDURE getBldgRoom(rcBuildingData OUT SYS_REFCURSOR, rcRoomData OUT SYS_REFCURSOR) IS
BEGIN
OPEN rcBuildingData FOR
select bldg_code, bldg_desc from IH_CSI_OWNER.BUILDING;
OPEN rcRoomData FOR
select bldg_code, room_code, room_desc from IH_CSI_OWNER.ROOM;
END getBldgRoom;
END GETBLDGROOM;
/
Код на C #
using System;
using System.Data;
using Oracle.DataAccess.Client; //Needs Oracle Data Access Client (ODAC)
namespace ClassLibrary
{
public class TwoTableDataSet
{
public DataSet getTwoTables()
{
OracleConnection conn = new OracleConnection();
//Normally we get the connection string from the web.config file or the app.config file
conn.ConnectionString = "Persist Security Info=False;User Id=*USER_NAME*;Password=*USER_PASSWORD*;Data Source=*DataBaseName*";
DataSet ds = new DataSet();
try
{
conn.Open();
//------------------------------------------------------------------------------------------------------
//Set up the select command
OracleCommand cmd = new OracleCommand();
cmd.BindByName = true; //If you do not bind by name, you must add parameters in the same order as they are listed in the procedure signature.
cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure; //A procedure in an oracle package
cmd.CommandText = "GETBLDGROOM.GetBldgRoom"; //The name of the procedure
cmd.Parameters.Add("rcBuildingData", OracleDbType.RefCursor, ParameterDirection.Output);
cmd.Parameters.Add("rcRoomData", OracleDbType.RefCursor, ParameterDirection.Output);
OracleDataAdapter da = new OracleDataAdapter();
da.SelectCommand = cmd;
//------------------------------------------------------------------------------------------------------
//get the data from the two tables in the procedure
da.Fill(ds);
//ds now contains ds.Tables[0] and ds.Tables[1]
//Let's give them names
ds.Tables[0].TableName = "BUILDINGS";
ds.Tables[1].TableName = "ROOMS";
//Let's add a relationship between the two tables
DataColumn parentColumn = ds.Tables["BUILDINGS"].Columns["BLDG_CODE"];
DataColumn childColumn = ds.Tables["ROOMS"].Columns["BLDG_CODE"];
DataRelation dr = new System.Data.DataRelation( "BuildingsRooms", parentColumn, childColumn);
ds.Relations.Add(dr);
}
catch (Exception ex)
{
//Add a breakpoint here to view the exception
//Normally the exception would be written to a log file or EventLog in the case of a Web app
//Alternatively, it could be sent to a WebService which logs errors and then it could work for both Web or Windows apps
Exception lex = ex;
}
finally
{
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
}
return ds;
}
}
}
Надеюсь, это поможет
Харви Сатер
Комментарии:
1. Идеальный. Это было именно то, что мне было нужно для решения моей проблемы.
2. Обратите внимание, что порядок таблиц в наборе данных
ds
соответствует порядку, в котором параметры добавляются вOracleCommand
. Это может отличаться от порядка формальных параметров, определенных в хранимой процедуре.