Sunday, February 11, 2018

Select from multiple tables in one call

Leave a Comment

In my code I have a page that includes information from 3 different tables. To show this information I make 3 SQL select calls and unite them in one list to pass as Model to my view. Can I do it with one SQL call? Data has no connection with one another.

My code:

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; } } 

If there is a way to load all 3 tables in one SQL request it will improve significantly the load time of this page.

Thank you.

7 Answers

Answers 1

You can get multiple result sets in a single request using a DataReader. You can use it with or without entity framework.

If you are using Entity Framework, you can pass a DbDataReader to ObjectContext.Translate method to translate multiple result set to requested object types. The command which is used to create the data reader can be a stored procedure, or you can simply use a command containing your queries to shape multiple result set.

Example

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();         }     } } 

If you are using SqlDataAdapter, you can simply pass a command containing your queries and then using Fill, fill a data set. The data adapter itself will use DataReader behind the scene.

Example

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); } 

Then you can shape the results to List<Table1> and List<Table2>.

Answers 2

You can use UNION ALL to merge multiple queries.

Do something like this:

SELECT * FROM Table1 UNION ALL SELECT * FROM Table2 

Edit:

You can do this if you want to know where a single record is from:

SELECT *, 1 AS TableName FROM Table1 UNION ALL SELECT *, 2 AS TableName FROM Table2 

This will add another column that can be used to split the array into 3 lists.

Answers 3

Assuming you are using EntityFramwork you can use EF Stored procedure that returns multiple result sets. Then map the result tables to your class object. Take a look here or google it. It will take one round to the DB.

Answers 4

DO NOT USE UNION. DataAdapter is weapon of choise.

var commandText = "SELECT * FROM Table1; SELECT * FROM Table2;"; var ds = new DataSet(); using (var da = new SqlDataAdapter(commandText, "your cn")) {     da.Fill(ds); } 

Using:

ds.Tables["Table1"]... ds.Tables["Table2"]... 

Answers 5

You can do something like this

SELECT  Info1, Info2  FROM Table1Data UNION ALL SELECT Id, Info2  FROM Table2Data; 

Then you can parse the result. Depends on the case but you can also consider using a transaction.

Answers 6

May be this can helpful to you.

Select the three tables in a single procedure as a separate result sets, and then in the C# side get the result sets and convert it into JSON format, and then from the JSON you can get the each table data into your list.

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"        // }       // ]      //} 

Answers 7

you can use below generic code snippet

      /// <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;     } 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment