【问题标题】:Select from multiple tables in one call一次调用从多个表中选择
【发布时间】:2018-07-11 18:40:07
【问题描述】:

在我的代码中,我有一个页面,其中包含来自 3 个不同表的信息。为了显示此信息,我进行了 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; }
}

如果有办法在一个 SQL 请求中加载所有 3 个表,它将显着缩短此页面的加载时间。

谢谢。

【问题讨论】:

  • 请说明您使用的是哪个 sql 驱动程序/orm!
  • sql server 2008
  • 所有 3 个表都没有共同点,所以我不能使用 UNION
  • 请向我们展示所有三个表中的数据的样子。每个表中包含样本数据及其类型的几行就足够了。
  • 这些表是属于同一个数据库还是属于不同的数据库?

标签: c# asp.net .net sql-server asp.net-mvc


【解决方案1】:

您可以使用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 个列表。

【讨论】:

  • 假设每个表中的列数和数据类型相同。
  • 是的,没错。我假设这些表看起来像他的 TableXData 类。
  • 只是觉得因为使用了SELECT *而值得指出,仅此而已:-)
  • 不幸的是所有 3 个表都没有共同点,所以我不能使用 UNION
  • Table2和Table3列表中的数据存放在哪里?你必须加入这些吗?
【解决方案2】:

你可以这样做

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

然后你就可以解析结果了。 视情况而定,但您也可以考虑使用事务。

【讨论】:

    【解决方案3】:

    这可能对你有帮助。

    在单个过程中选择三个表作为单独的结果集,然后在C#端获取结果集并将其转换为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"
           // }
          // ]
         //}
    

    【讨论】:

      【解决方案4】:

      假设您使用的是 EntityFramwork,您可以使用返回多个结果集的 EF 存储过程。然后将结果表映射到您的类对象。看看heregoogle it。 DB 需要一轮。

      【讨论】:

        【解决方案5】:

        您可以使用DataReader 在单个请求中获取多个结果集。您可以在有或没有实体框架的情况下使用它。

        如果您使用的是实体框架,则可以将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&lt;Table1&gt;List&lt;Table2&gt;

        【讨论】:

        • 有什么方法可以直接调用 sp 并获取我们可以与 nextresult() 一起使用的结果集?
        【解决方案6】:

        不要使用联合。 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"]...
        

        【讨论】:

          【解决方案7】:

          你可以使用下面的通用代码sn-p

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

          【讨论】:

          • 还有为什么你有myCommand.ExecuteNonQuery();,然后是myAdapter.Fill(ds);
          猜你喜欢
          • 2012-03-05
          • 2011-02-22
          • 1970-01-01
          • 2018-02-07
          • 1970-01-01
          • 1970-01-01
          • 2011-03-04
          • 1970-01-01
          • 2015-10-27
          相关资源
          最近更新 更多