Создайте строго типизированный набор данных для хранимой процедуры, которая возвращает более одной таблицы - PullRequest
0 голосов
/ 20 июня 2019

У меня есть хранимая процедура, которая выполняет 3 выбора.Как создать строго типизированный набор данных, который может получить доступ ко всем 3 таблицам и прочитать данные.Visual Studio по умолчанию генерирует набор данных только с 1-й таблицей

Я уже пытался использовать Visual Studio Typed Dataset для перетаскивания хранимой процедуры.

Хранимая процедура выглядит примерно так:

Create Procedure GetData
As
Begin
Select ColA, ColB, ColC from TableA
Select ColD, ColE, ColF from TableB
Select ColG, ColH, ColI from TableC
End

1 Ответ

0 голосов
/ 20 июня 2019

Если вы отчаянно пытаетесь сделать это, я не думаю, что вам удастся получить чисто строго типизированное дизайнерское решение; Табличные адаптеры предназначены для посредничества между локальным представлением данных db (которое строго типизировано) и датированным запросом к базе данных, который возвращает строки. Таблица в адаптере таблицы связана с таблицей данных, а не с таблицей базы данных.

Один табличный адаптер не предназначен для использования в качестве посредника между 3 локальными таблицами данных и удаленной процедурой, которая обеспечивает вывод 3 запросов к базе данных. Прежде всего, он не может этого сделать, потому что нет ничего, что можно было бы использовать на стороне клиента для идентификации, для вашего sql of ...

Select ColA, ColB, ColC from TableA
Select ColD, ColE, ColF from TableB
Select ColG, ColH, ColI from TableC

... что результаты из select * from TableA должны помещаться в TableADataTable в вашем наборе данных и т. Д. Тот факт, что данные, полученные из таблицы A, теряется при передаче по проводам, потому что это совершенно не имеет значения и может даже не быть быть правдой.

Когда табличный адаптер правильно используется с одним выбором, он неявно знает, в какую таблицу данных должны быть помещены результаты. TableADataTable имеет соответствующий TableATableAdapter, а TableATableAdapter выбирает данные где-то в БД и сохраняет их в TableADataTable - есть нет другой таблицы в наборе данных, которой TableATableAdapter предназначен для манипулирования, поэтому ему не нужно никаких подсказок о том, куда блок данных отправляется после выполнения запроса. TableATableAdapter может даже быть загружен запросом, который вообще не возвращает никаких данных из базы данных TableA; до тех пор, пока выполняемый запрос создает набор столбцов с нужным номером и типом, эти данные будут помещаться в TableADataTable, потому что это то, что TableATableAdapter жестко кодирует. Он не служит никаким другим датируемым и не интересуется каким-либо другим датируемым.

Поскольку ваша хранимая процедура не может указать табличному адаптеру, какой из наборов результатов должен быть сохранен в какой таблице, рассматриваемое решение не может работать.

Простое правило: «одна собака, одна выполнена» - «один набор результатов запроса БД, одна таблица-адаптер, один строго типизированный тип данных»

Поэтому я настоятельно рекомендую вам использовать эти вещи так, как они были предназначены:

  • Создание 3 таблиц-адаптеров и соответствующих таблиц данных для TableA, TableB и TableC
  • Заполните каждый код самостоятельно:

var ds = new StronglyTypedDataSet();
var ata as new TableATableAdapter();
ata.Fill(ds);
var bta as new TableBTableAdapter();
bta.Fill(ds);
var cta as new TableCTableAdapter();
cta.Fill(ds);

«Мы хотели бы избежать нескольких вызовов БД для одной страницы», на самом деле не имеет смысла - это похоже на решение проблемы, которую вы себе представляли, а не на то, что действительно произойдет. Так мало выигрыша в производительности можно получить, если попытаться выполнить эти вещи одним ударом, а не 3. Вы можете не согласиться, но протестируйте его - не обманывайте себя. Соединения объединяются, операторы кэшируются и подготавливаются, 3 оператора могут выполняться одновременно, если вы действительно думаете, что это сильно поможет.

В конце концов, если у вас есть 9 мегабайт данных, которые нужно извлечь из базы данных, разница в том, что 3 извлечения по 3 МБ каждый против 1 извлечения из 9 будет крошечной; Вы не ждете 30 секунд, чтобы открыть соединение, читая 3 МБ в секунду, ожидая еще 30 секунд, чтобы закрыть его, и вам придется делать все это снова (общее время 183 секунды) и все узкие места связаны с управлением соединением , Даже если у вас было соединение с супер-задержкой, для передачи SELECT которого потребуется 30 секунд, а для начала чтения данных - еще 30 секунд, вы можете запустить 3 запроса одновременно, и по определению для отправки сообщения потребуется то же время. 3 ВЫБРАТЬ, чтобы вызвать 1 вызов процедуры (оба занимают 61 секунду)


Если вы не можете согласиться с тем, что причина попытки сделать все это в одном случае ложная, вы можете продолжать пытаться делать это с помощью выбранного вами метода, и в этом случае я думаю, что вам придется выбирать:

Использование стандартного адаптера данных и набора данных

и затем переместить данные в набор для работы с ним

SqlConnection con = new SqlConnection("YourConnection String");
SqlDataAdapter da = new SqlDataAdapter();
DataSet ds = new DataSet();
SqlCommand cmd = new SqlCommand("sproc", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@p1", whatever); //if you have parameters.
SqlDataAdapter da= new SqlDataAdapter(cmd);
da.Fill(ds);
con.Close();

Теперь у вас есть набор данных с 3 таблицами, ваша задача - выяснить, какая таблица какая. Давайте предположим, что ds.Tables [0] для TableA:

foreach(var ro in ds.Tables[0].Rows)
  typedDs.TableA.AddTableARow(ro.ItemArray);

Повторите это для таблиц b и c

Преобразуйте ваши 3 запроса в 1

Ваш пример показывает, что все 3 ваши таблицы имеют одинаковое количество столбцов. Если столбцы также относятся к одному и тому же типу, вы можете объединить запросы, загрузить их в один адаптер таблицы и заполнить их в один тип данных со строгой типизацией. Затем у вас может быть еще немного работы, чтобы разбить их на отдельные таблицы данных. Возможно, измените этот запрос, чтобы он возвращал столбец, чтобы вы могли отслеживать, откуда поступили данные:

Select 'tableA' as wherefrom, ColA, ColB, ColC from TableA
UNION ALL
Select 'tableB' as wherefrom, ColD, ColE, ColF from TableB
UNION ALL
Select 'tableC' as wherefrom, ColG, ColH, ColI from TableC

Это беспорядок, хлопоты, взломать


Почему это так сложно? Ну что ж ... процитирую еще одну старую поговорку: если это сложно, ты делаешь это неправильно. Адаптеры таблиц были разработаны X-способом, а вы пытаетесь использовать их Y-способом. Сделайте шаг назад и изучите причины, по которым вы это делаете - вот в чем настоящая проблема

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...