将C#SQL循环转换为Linq

本文关键字:Linq 转换 循环 C#SQL | 更新日期: 2023-09-27 18:25:44

我有一个名为ListTypes的列表,其中包含10种类型的产品。下面的存储过程循环并获取循环产品的每个记录,并将其存储在列表ListIds中。这正在扼杀我的sql框,因为我有200多个用户整天都在执行它。

我知道循环sql语句不是一个好的体系结构,但这是我使其工作的唯一方法。有什么想法我可以在不循环的情况下做到这一点吗?也许是林克的一句话,我从来没有用过这么大的林克。非常感谢。

protected void GetIds(string Type, string Sub)
{
   LinkedIds.Clear();
  using (SqlConnection cs = new SqlConnection(connstr))
  {
    for (int x = 0; x < ListTypes.Count; x++)
    {
        cs.Open();
        SqlCommand select = new SqlCommand("spUI_LinkedIds", cs);
        select.CommandType = System.Data.CommandType.StoredProcedure;
        select.Parameters.AddWithValue("@Type", Type);
        select.Parameters.AddWithValue("@Sub", Sub);
        select.Parameters.AddWithValue("@TransId", ListTypes[x]);
        SqlDataReader dr = select.ExecuteReader();
        while (dr.Read())
        {
            ListIds.Add(Convert.ToInt32(dr["LinkedId"]));
        }
        cs.Close();
    }
  }
}

将C#SQL循环转换为Linq

不是一个完整的答案,但这不适合发表评论。你至少可以更新你现有的代码,使其更高效,如下所示:

protected List<int> GetIds(string Type, string Sub, IEnumerable<int> types)
{
    var result = new List<int>();
    using (SqlConnection cs = new SqlConnection(connstr))
    using (SqlCommand select = new SqlCommand("spUI_LinkedIds", cs))
    {
        select.CommandType = System.Data.CommandType.StoredProcedure;
        //Don't use AddWithValue! Be explicit about your DB types
        // I had to guess here. Replace with the actual types from your database
        select.Parameters.Add("@Type", SqlDBType.VarChar, 10).Value = Type;
        select.Parameters.Add("@Sub", SqlDbType.VarChar, 10).Value = Sub;
        var TransID = select.Parameters.Add("@TransId", SqlDbType.Int);
        cs.Open();
        foreach(int type in types)
        {
            TransID.Value = type;
            SqlDataReader dr = select.ExecuteReader();
            while (dr.Read())
            {
                result.Add((int)dr["LinkedId"]);
            }
        }
    }
    return result;
}

请注意,通过这种方式,您只能打开和关闭一次连接。通常在ADO.Net中,最好使用一个新的连接,并为每个查询重新打开它。例外情况是这样的。此外,循环中唯一以这种方式更改的是一个参数值。最后,最好设计不依赖于其他类状态的方法。此方法不再需要知道ListTypesListIds类变量,这使得可以(除其他外)对该方法进行更好的单元测试。

同样,这并不是一个完整的答案;这只是一个渐进的改进。您真正需要做的是编写另一个接受表值参数的存储过程,并基于现有存储过程中的查询来与表值参数JOIN,这样所有这些都将适合一条SQL语句。但是,在您共享存储过程代码之前,这是我所能为您提供的最大帮助。

除了其他人写的改进。你可以把你的ID插入一个临时表,然后制作一个

SELECT * from WhatEverTable WHERE transid in (select transid from #tempTable)

在MSSQL上,这真的很快。

当您不使用MSSQL时,一个具有联接的优秀SQL Select可能比Select IN更快。您必须在DBMS上自己测试这些情况。

根据您的评论:
The idea is lets say I have a table and I have to get all records from the table that has this 10 types of products. How can I get all of this products? But this number is dynamic.

所以。。。为什么要使用存储过程?为什么不查询表?

//If [Type] and [Sub] arguments are external inputs - as in, they come from a user request or something - they should be sanitized. (remove or escape ''' and apostrophe signs)
//create connection
string queryTmpl = "SELECT LinkedId FROM [yourTable] WHERE [TYPE] = '{0}' AND [SUB] = '{1}' AND [TRANSID] IN ({2})";
string query = string.Format(queryTmpl, Type, Sub, string.Join(", ", ListTypes);
SqlCommand select = new SqlCommand(query, cs);
//and so forth

要使用Linq-To-SQL,您需要将表映射到一个类。这将使查询更易于执行。