Выбрать из нескольких таблиц за один вызов
В моем коде у меня есть страница, содержащая информацию из трех разных таблиц. Чтобы показать эту информацию, я делаю 3 запроса выбора SQL и объединяю их в один список, чтобы передать его в качестве модели. Могу ли я сделать это с помощью одного вызова SQL? Данные не имеют связи друг с другом.
Мой код:
public ActionResult Index()
{
StorePageData PageData = new StorePageData();
return View(PageData);
}
public class StorePageData
{
public List<Table1Data> Table1 { get; set; }
public List<Table2Data> Table2 { get; set; }
public List<Table3Data> Table3 { get; set; }
public StorePageData()
{
Table1 = //loading from Database1
Table2 = //loading from Database2
Table3 = //loading from Database3
}
}
public class Table1Data
{
public int Id { get; set; }
public double Info1 { get; set; }
public string Info2 { get; set; }
}
public class Table2Data
{
public int Id { get; set; }
public List<int> Info1 { get; set; }
public List<int> Info2 { get; set; }
}
public class Table3Data
{
public int Id { get; set; }
public List<string> Info1 { get; set; }
public List<string> Info2 { get; set; }
}
Если есть способ загрузить все 3 таблицы в один запрос SQL, это значительно улучшит время загрузки этой страницы.
Спасибо.
Ответы
Ответ 1
Вы можете получить несколько наборов результатов в одном запросе, используя DataReader
. Вы можете использовать его с или без структуры лица.
Если вы используете Entity Framework, вы можете передать метод DbDataReader
- ObjectContext.Translate
, чтобы преобразовать несколько результирующих наборов в запрошенные типы объектов. Команда, которая используется для создания устройства чтения данных, может быть хранимой процедурой, или вы можете просто использовать команду, содержащую ваши запросы, для формирования множества результатов.
Пример
List<Table1> list1;
List<Table2> list2;
using (var cn = new SqlConnection(@"Connection String"))
{
cn.Open();
using (var cmd = cn.CreateCommand())
{
cmd.CommandText = "SELECT * FROM Table1; SELECT * FROM Table2";
var reader = cmd.ExecuteReader();
using (var db = new YourDbContext())
{
var context = ((IObjectContextAdapter)db).ObjectContext;
list1 = context.Translate<Table1>(reader).ToList();
reader.NextResult();
list2 = context.Translate<Table2>(reader).ToList();
}
}
}
Если вы используете SqlDataAdapter
, вы можете просто передать команду, содержащую ваши запросы, а затем, используя Fill
, заполнить набор данных. Сам адаптер данных будет использовать DataReader
за сценой.
Пример
var connectionString = @"Connection String";
var commandText = "SELECT * FROM Table1; SELECT * FROM Table2;";
var ds = new DataSet();
using (var da = new SqlDataAdapter(commandText, connectionString))
{
da.Fill(ds);
}
Затем вы можете сформировать результаты в List<Table1>
и List<Table2>
.
Ответ 2
Вы можете использовать UNION ALL
для объединения нескольких запросов.
Сделайте что-то вроде этого:
SELECT * FROM Table1
UNION ALL
SELECT * FROM Table2
Редактировать:
Вы можете сделать это, если хотите узнать, где находится одна запись:
SELECT *, 1 AS TableName FROM Table1
UNION ALL
SELECT *, 2 AS TableName FROM Table2
Это добавит еще один столбец, который можно использовать для разделения массива на 3 списка.
Ответ 3
Предполагая, что вы используете EntityFramwork, вы можете использовать хранимую процедуру EF, которая возвращает несколько наборов результатов. Затем сопоставьте таблицы результатов с объектом класса. Взгляните сюда или google. Это займет один раунд в БД.
Ответ 4
НЕ ИСПОЛЬЗУЙТЕ СОЮЗ. DataAdapter - это оружие выбора.
var commandText = "SELECT * FROM Table1; SELECT * FROM Table2;";
var ds = new DataSet();
using (var da = new SqlDataAdapter(commandText, "your cn"))
{
da.Fill(ds);
}
С помощью:
ds.Tables["Table1"]...
ds.Tables["Table2"]...
Ответ 5
Вы можете сделать что-то подобное
SELECT Info1, Info2
FROM Table1Data
UNION ALL
SELECT Id, Info2
FROM Table2Data;
Затем вы можете проанализировать результат. Зависит от случая, но вы также можете рассмотреть возможность использования транзакции.
Ответ 6
Может быть, это может вам помочь.
Выберите три таблицы в одной процедуре в виде отдельных наборов результатов, а затем на стороне С# получите результирующие наборы и преобразуйте их в формат JSON, а затем из JSON вы можете получить данные таблицы в свой список.
DataSet dataSet = new DataSet("dataSet");
dataSet.Namespace = "NetFrameWork";
DataTable table = new DataTable();
DataColumn idColumn = new DataColumn("id", typeof(int));
idColumn.AutoIncrement = true;
DataColumn itemColumn = new DataColumn("item");
table.Columns.Add(idColumn);
table.Columns.Add(itemColumn);
dataSet.Tables.Add(table);
for (int i = 0; i < 2; i++)
{
DataRow newRow = table.NewRow();
newRow["item"] = "item " + i;
table.Rows.Add(newRow);
}
dataSet.AcceptChanges();
string json = JsonConvert.SerializeObject(dataSet, Formatting.Indented);
Console.WriteLine(json);
//{
// "Table1": [
// {
// "id": 0,
// "item": "item 0"
// },
// {
// "id": 1,
// "item": "item 1"
// }
// ]
//"Table2": [
// {
// "id": 0,
// "item": "item 0",
// "rate": 200.00
// },
// {
// "id": 1,
// "item": "item 1",
// "rate": 225.00
//}
// ]
// "Table3": [
// {
// "id": 0,
// "item": "item 0",
// "rate": 200.00,
// "UOM" : "KG"
// },
// {
// "id": 1,
// "item": "item 1",
// "rate": 225.00,
// "UOM" : "LTR"
// }
// ]
//}
Ответ 7
вы можете использовать ниже общий фрагмент кода
/// <method>
/// Select Query
/// </method>
public DataTable executeSelectQuery(String _query, SqlParameter[] sqlParameter)
{
SqlCommand myCommand = new SqlCommand();
DataTable dataTable = new DataTable();
dataTable = null;
DataSet ds = new DataSet();
try
{
myCommand.Connection = openConnection();
myCommand.CommandText = _query;//or proc
myCommand.Parameters.AddRange(sqlParameter);
myAdapter.SelectCommand = myCommand;
myAdapter.Fill(ds);
dataTable = ds.Tables[0];//as per your requirement
}
catch (SqlException e)
{//any logger
Console.Write("Error - Connection.executeSelectQuery - Query: " + _query + " \nException: " + e.StackTrace.ToString());
return null;
}
return dataTable;
}