Выбрать из нескольких таблиц за один вызов

В моем коде у меня есть страница, содержащая информацию из трех разных таблиц. Чтобы показать эту информацию, я делаю 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;
    }