将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();
}
}
}
不是一个完整的答案,但这不适合发表评论。你至少可以更新你现有的代码,使其更高效,如下所示:
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中,最好使用一个新的连接,并为每个查询重新打开它。例外情况是这样的。此外,循环中唯一以这种方式更改的是一个参数值。最后,最好设计不依赖于其他类状态的方法。此方法不再需要知道ListTypes
和ListIds
类变量,这使得可以(除其他外)对该方法进行更好的单元测试。
同样,这并不是一个完整的答案;这只是一个渐进的改进。您真正需要做的是编写另一个接受表值参数的存储过程,并基于现有存储过程中的查询来与表值参数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,您需要将表映射到一个类。这将使查询更易于执行。