如何在 List<> 中捕获此存储过程的结果?
How can I capture the results of this Stored Procedure in a List<>?
我已经为此苦苦挣扎了至少 3 个小时,而且我对 C# 还有些陌生,尤其是 return 从 SQL 服务器中的存储过程中获取多行。
我想return一个存储过程的结果:
create procedure ingredientNames_givenDishId
@dishid inT
AS
SELECT
a.ingredientname --given dish id, return ingredientnames
FROM
dbo.purple_ingredients a
JOIN
dbo.purple_dish_ingredients b ON a.ingredientid = b.ingredientid
WHERE
b.dishid = @dishid
这是我在 SQL 服务器中执行相同程序时的结果,其中 10 为 dishid:
我的 C# 代码:
private void btnIngs3FromDishId_Click(object sender, EventArgs e) {
List<Ingredient> someIngs = new List<Ingredient>();
Purple_DataClasses1DataContext dbContextCreateMenu =
new Purple_DataClasses1DataContext(DataHandler.theConnectionString);
foreach (var row in dbContextCreateMenu.ingredientNames_givenDishId(10))
MessageBox.Show(row.ToString());
我也试过:
var thing = dbContextCreateMenu.ingredientNames_givenDishId(10);
var anotherThing = thing.AsEnumerable();
foreach (var subthing in anotherThing)
当我设置断点并将鼠标悬停在 "anotherThing" 上时,最后一个示例实际上显示了 3 个字符串值:
我可以用鼠标向下钻取并查看一次字符串值,然后我会
获得有关后续尝试的通知:{"The query results cannot be enumerated more than once."}
如有任何帮助,我们将不胜感激。谢谢!
@Enigmativity:这很有帮助,而且实施起来非常简单。这是我最终得到的结果,效果很好:
var thing= dbContextCreateMenu.ingredientNames_givenDishId(10);
var anotherThing = thing.ToList();
MessageBox.Show(anotherThing.ElementAt(0).ingredientname);
@Sharag & marc_s:这个老方法也能用!!非常感激。其他刚开始使用它的人需要注意的几点:我需要这一行:
cmd.CommandType = CommandType.StoredProcedure;
我还需要在此行中将 @dishid 显式设置为 int,否则编译器会将其视为对象:
cmd.Parameters.AddWithValue("@dishid", Convert.ToInt32(aValue));
我不是 LINQ 方面的专家,但如果您想要始终有效的旧方法,请看这里:
List<String> lt = new List<string>();
try{
if (con.State == System.Data.ConnectionState.Closed)
con.Open();
cmd.CommandText = qr;\the query
SqlDataAdapter adp = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
adp.Fill(dt);
for(int i=0;i<dt.Rows.Count;i++)
{lt.Add(dt.Rows[i][0].toString());}
}
catch (SqlException exc)
{ MessageBox.Show(exc.Message); }
在 C# 端,您可以使用 reader、数据表、适配器进行访问。
数据 reader 的示例代码如下所示
SqlConnection connection = new SqlConnection(ConnectionString);
command = new SqlCommand("TestProcedure", connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
connection.Open();
reader = command.ExecuteReader();
List<Test> TestList = new List<Test>();
Test test;
while (reader.Read())
{
test = new Test();
test.ID = int.Parse(reader["ID"].ToString());
test.Name = reader["Name"].ToString();
TestList.Add(test);
}
最简单的做法是将以下代码中的 .AsEnumerable()
替换为 .ToArray()
:
var thing = dbContextCreateMenu.ingredientNames_givenDishId(10);
var anotherThing = thing.AsEnumerable();
foreach (var subthing in anotherThing)
成功:
var thing = dbContextCreateMenu.ingredientNames_givenDishId(10);
var anotherThing = thing.ToArray();
foreach (var subthing in anotherThing)
.AsEnumerable()
的问题在于它是一个相当弱的运算符,除了执行转换操作外什么都不做。
这是"System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089":
的反编译源
[__DynamicallyInvokable]
public static IEnumerable<TSource> AsEnumerable<TSource>(this IEnumerable<TSource> source)
{
return source;
}
它实际上并没有做任何事情来强制执行您的查询。
调用.ToArray()
确实会强制执行。
另一种方法是调用 .ToList()
。我不提倡这样做,除非您知道要更改列表的成员。每个的性能几乎相同。 .ToArray()
和 .ToList()
都将元素添加到最初以 4 个元素开始的数组,然后每次达到当前容量时将容量加倍。但是,调用 .ToArray()
将提高内存效率,因为它在返回数组之前所做的最后一件事是截断缓冲区。因此,包含 1,025 个项目的 List<T>
将在内部包含 2,048 个成员,但是包含 1,025 个元素的 T[]
将仅包含 1,025 个项目 - 用于构造 2,048 个成员的缓冲区可立即用于垃圾回收。
我已经为此苦苦挣扎了至少 3 个小时,而且我对 C# 还有些陌生,尤其是 return 从 SQL 服务器中的存储过程中获取多行。
我想return一个存储过程的结果:
create procedure ingredientNames_givenDishId
@dishid inT
AS
SELECT
a.ingredientname --given dish id, return ingredientnames
FROM
dbo.purple_ingredients a
JOIN
dbo.purple_dish_ingredients b ON a.ingredientid = b.ingredientid
WHERE
b.dishid = @dishid
这是我在 SQL 服务器中执行相同程序时的结果,其中 10 为 dishid:
我的 C# 代码:
private void btnIngs3FromDishId_Click(object sender, EventArgs e) {
List<Ingredient> someIngs = new List<Ingredient>();
Purple_DataClasses1DataContext dbContextCreateMenu =
new Purple_DataClasses1DataContext(DataHandler.theConnectionString);
foreach (var row in dbContextCreateMenu.ingredientNames_givenDishId(10))
MessageBox.Show(row.ToString());
我也试过:
var thing = dbContextCreateMenu.ingredientNames_givenDishId(10);
var anotherThing = thing.AsEnumerable();
foreach (var subthing in anotherThing)
当我设置断点并将鼠标悬停在 "anotherThing" 上时,最后一个示例实际上显示了 3 个字符串值:
我可以用鼠标向下钻取并查看一次字符串值,然后我会 获得有关后续尝试的通知:{"The query results cannot be enumerated more than once."}
如有任何帮助,我们将不胜感激。谢谢!
@Enigmativity:这很有帮助,而且实施起来非常简单。这是我最终得到的结果,效果很好:
var thing= dbContextCreateMenu.ingredientNames_givenDishId(10);
var anotherThing = thing.ToList();
MessageBox.Show(anotherThing.ElementAt(0).ingredientname);
@Sharag & marc_s:这个老方法也能用!!非常感激。其他刚开始使用它的人需要注意的几点:我需要这一行:
cmd.CommandType = CommandType.StoredProcedure;
我还需要在此行中将 @dishid 显式设置为 int,否则编译器会将其视为对象:
cmd.Parameters.AddWithValue("@dishid", Convert.ToInt32(aValue));
我不是 LINQ 方面的专家,但如果您想要始终有效的旧方法,请看这里:
List<String> lt = new List<string>();
try{
if (con.State == System.Data.ConnectionState.Closed)
con.Open();
cmd.CommandText = qr;\the query
SqlDataAdapter adp = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
adp.Fill(dt);
for(int i=0;i<dt.Rows.Count;i++)
{lt.Add(dt.Rows[i][0].toString());}
}
catch (SqlException exc)
{ MessageBox.Show(exc.Message); }
在 C# 端,您可以使用 reader、数据表、适配器进行访问。
数据 reader 的示例代码如下所示
SqlConnection connection = new SqlConnection(ConnectionString);
command = new SqlCommand("TestProcedure", connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
connection.Open();
reader = command.ExecuteReader();
List<Test> TestList = new List<Test>();
Test test;
while (reader.Read())
{
test = new Test();
test.ID = int.Parse(reader["ID"].ToString());
test.Name = reader["Name"].ToString();
TestList.Add(test);
}
最简单的做法是将以下代码中的 .AsEnumerable()
替换为 .ToArray()
:
var thing = dbContextCreateMenu.ingredientNames_givenDishId(10);
var anotherThing = thing.AsEnumerable();
foreach (var subthing in anotherThing)
成功:
var thing = dbContextCreateMenu.ingredientNames_givenDishId(10);
var anotherThing = thing.ToArray();
foreach (var subthing in anotherThing)
.AsEnumerable()
的问题在于它是一个相当弱的运算符,除了执行转换操作外什么都不做。
这是"System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089":
的反编译源[__DynamicallyInvokable]
public static IEnumerable<TSource> AsEnumerable<TSource>(this IEnumerable<TSource> source)
{
return source;
}
它实际上并没有做任何事情来强制执行您的查询。
调用.ToArray()
确实会强制执行。
另一种方法是调用 .ToList()
。我不提倡这样做,除非您知道要更改列表的成员。每个的性能几乎相同。 .ToArray()
和 .ToList()
都将元素添加到最初以 4 个元素开始的数组,然后每次达到当前容量时将容量加倍。但是,调用 .ToArray()
将提高内存效率,因为它在返回数组之前所做的最后一件事是截断缓冲区。因此,包含 1,025 个项目的 List<T>
将在内部包含 2,048 个成员,但是包含 1,025 个元素的 T[]
将仅包含 1,025 个项目 - 用于构造 2,048 个成员的缓冲区可立即用于垃圾回收。