本着 Donnies 回答的精神,我提供了一个简单的 SQL 示例,说明如何在使用比动态构造的 SQL 更安全的机制之后检索您的内容(正如其他人所建议的那样)
在简单的情况下,您应该为数据库中的每个实体为应用程序可用的每个 Create、Read、Update、Delete 操作创建一个存储过程。(这在大型生产系统中并不是 100% 正确,但它比在应用程序中构建的动态生成的 SQL 更好)
现在对于 READ,如果没有提供参数,这将列出所有内容。这是我工作中的数据库架构师讲授的一种方法的简化版本——这里我们没有将检索存储过程与列表过程分开,它们实际上是相同的操作。从长远来看,这将以更少的 SQL 代码来维护。
CREATE PROCEDURE usp_ReadName
@name_id bigint=NULL
AS
BEGIN
SET NOCOUNT ON;
if (@name_id IS NULL)
SELECT name_id,name,description
from name with(nolock)
else
select name_id,name,description
from name with(nolock)
where name_id = @name_id
END
GO
现在是 C# 方面。为了保存结果,我们定义了一个数据传输实体。一般来说,这些比数据表更轻,使用起来更快更有效。如果速度、大量数据或有限的内存不是问题,只需使用数据表即可。(平均而言,您将节省大约 40% 以上的内存和大约 10% 的速度 - 100K 以上结构的记录使用数据表的峰值内存使用量为 140MB,而 DTE 峰值为 78MB)
/// <summary>
/// A simple data transfer entity
/// </summary>
public struct name_data
{
public long name_id;
public string name;
public string description;
public name_data(long id, string n, string d)
{
name_id = id;
name = n;
description = d;
}
}
现在我们使用可空参数语法在 C# 中捕获结果。此代码假定您已经打开了 sql 连接
conn.Open();
using (SqlCommand cmd = new SqlCommand("usp_ReadName",conn))
{
cmd.CommandType = CommandType.StoredProcedure;
if (id.HasValue)
cmd.Parameters.Add("@name_id", SqlDbType.BigInt).Value = id.Value;
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
dte.name_data item = new dte.name_data(
(long)reader["name_id"],
reader["name"].ToString(),
reader["description"].ToString());
items.Add(item);
}
}
}
}