Я привык (из Ады с использованием libpq) к
открыть курсор
получить некоторые ключевые ценности
используйте эти ключевые значения в качестве параметров привязки для других операторов.
Но вместо этого я получаю исключение Npgsql.NpgsqlOperationInProgressException.
Однажды я получил эту работу с sql-сервером, но решил это, добавив 'MARS' в строку подключения (несколько наборов активных записей)
Могу я сделать здесь что-то подобное?
Вот что я пытаюсь сделать:
conn.Open();
// Define a query
NpgsqlCommand cmdGetSelectionIds = new NpgsqlCommand("select distinct(R.SELECTIONID) from ARUNNERS R, AMARKETS M " +
"where true " +
"and M.MARKETID = R.MARKETID " +
"and M.MARKETTYPE = 'WIN' " +
"and R.STATUS <> 'REMOVED'", conn);
NpgsqlCommand cmdNumWins = new NpgsqlCommand("select count('a') from ARUNNERS R, AMARKETS M " +
"where true " +
"and M.MARKETID = R.MARKETID " +
"and R.SELECTIONID = @selid " +
"and M.MARKETTYPE = 'WIN' " +
"and R.STATUS = 'WINNER'", conn);
NpgsqlCommand cmdNumPlcs = new NpgsqlCommand("select count('a') from ARUNNERS R, AMARKETS M " +
"where true " +
"and M.MARKETID = R.MARKETID " +
"and R.SELECTIONID = @selid " +
"and M.MARKETTYPE = 'PLACE' " +
"and R.STATUS = 'WINNER'", conn);
NpgsqlCommand cmdNumLosses = new NpgsqlCommand("select count('a') from ARUNNERS R, AMARKETS M " +
"where true " +
"and M.MARKETID = R.MARKETID " +
"and R.SELECTIONID = @selid " +
"and M.MARKETTYPE = 'WIN' " +
"and R.STATUS = 'LOSER'", conn);
NpgsqlDataReader drGetSelectionIds = cmdGetSelectionIds.ExecuteReader();
while (drGetSelectionIds.Read())
{
selid = drGetSelectionIds.GetInt32(0);
cmdNumWins.Parameters.AddWithValue("selid", selid);
using (NpgsqlDataReader drNumWins = cmdNumWins.ExecuteReader())
{
if (drNumWins.Read()) numWins = drNumWins.GetInt32(0);
}
using (NpgsqlDataReader drNumPlcs = cmdNumPlcs.ExecuteReader())
{
if (drNumPlcs.Read()) numPlcs = drNumPlcs.GetInt32(0);
}
using (NpgsqlDataReader drNumLosses = cmdNumLosses.ExecuteReader()) {
if (drNumLosses.Read()) numPlcs = drNumLosses.GetInt32(0);
}
Console.Write("selid : {0} \t num W {1} \t num P {2} num L {3} \t points {4}\n", selid, numWins, numPlcs, numLosses, (3.0*numWins + numPlcs )/(numWins+numLosses));
}
// Close connection
conn.Close();
Да, я мог бы прочитать первый оператор в списке и перебрать его, но у меня есть довольно старый код, созданный, как указано выше.
/ Бьорн
2 ответа
Проблема в том, что NpgSql позволяет одновременно открывать только одно средство чтения данных. Если у вас есть ситуация, когда вам нужно, чтобы несколько считывателей данных одновременно открывали одно и то же соединение, я бы сказал, что может быть лучший способ достижения вашей конечной цели.
Итак, отказ от ответственности ... не делайте этого. НО, если бы вы хотели сделать то, что описали выше, это был бы способ сделать это:
cmdNumWins.Parameters.Add(new NpgsqlParameter("@selid", NpgsqlDbType.Integer));
cmdNumPlcs.Parameters.Add(new NpgsqlParameter("@selid", NpgsqlDbType.Integer));
cmdNumLosses.Parameters.Add(new NpgsqlParameter("@selid", NpgsqlDbType.Integer));
List<int> idList = new List<int>();
using (NpgsqlDataReader drGetSelectionIds = cmdGetSelectionIds.ExecuteReader())
{
while (drGetSelectionIds.Read())
idList.Add(drGetSelectionIds.GetInt32(0));
drGetSelectionIds.Close();
}
foreach (int selid in idList)
{
cmdNumWins.Parameters[0].Value = selid;
cmdNumPlcs.Parameters[0].Value = selid;
cmdNumLosses.Parameters[0].Value = selid;
numWins = Convert.ToInt32(cmdNumWins.ExecuteScalar());
numPlcs = Convert.ToInt32(cmdNumPlcs.ExecuteScalar());
numLosses = Convert.ToInt32(cmdNumLosses.ExecuteScalar());
Console.Write("selid : {0} \t num W {1} \t num P {2} num L {3} \t points {4}\n", selid,
numWins, numPlcs, numLosses, (3.0 * numWins + numPlcs) / (numWins + numLosses));
}
Лучше всего сделать все это одним запросом:
select
r.selectionid,
count (1) filter (where m.markettype = 'WIN' and r.status = 'WINNER') as win,
count (1) fitler (where m.markettype = 'PLACE' and r.status = 'WINNER') as place,
count (1) filter (where m.markettype = 'WIN' and r.status = 'LOSER') as lose
from
arunners r
join amarkets m on m.marketid = r.marketid
where
r.status != 'REMOVED'
group by
r.selectionid
Возможно, я упустил некоторые нюансы в вашей логике, но, надеюсь, вы уловили идею. Это должно сделать сразу, быстро и эффективно то, что делает ваша логика C #. Это будет намного удобнее для базы данных, а для больших наборов данных должно быть немного быстрее.
Как было написано выше, Npgsql действительно позволяет одновременно открывать только одно средство чтения данных в данном соединении (в отличие от функции MARS MSSQL). Однако вы можете сделать что-то похожее , вручную используя курсоры на стороне сервера самостоятельно а> . Другими словами, вы можете запустить один запрос и извлечь X строк из его курсора, а затем выполнить второй запрос на основе результатов первого. Вы всегда можете вернуться к первому запросу и получить еще X строк и т. Д.
Другими словами, в то время как Npgsql не допускает одновременного использования более одного читателя , PostgreSQL допускает более одного запроса (или курсора) одновременно.
Похожие вопросы
Новые вопросы
c#
C # (произносится как «резкий») - это высокоуровневый, статически типизированный язык программирования с несколькими парадигмами, разработанный Microsoft. Код C # обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, включая, среди прочего, .NET Framework, .NET Core и Xamarin. Используйте этот тег для вопросов о коде, написанном на C # или в формальной спецификации C #.