我有这个问题正在吃我的脑海。问题是_reader没有读任何东西。
我有这段代码:
public DataEntities.Usuario GetUser(string field, string value)
{
using (SqlConnection connection = new SqlConnection(@"connectionstring"))
{
using (SqlCommand query = new SqlCommand())
{
DataEntities.Usuario _usuario = new DataEntities.Usuario();
if (field == "id" || field == "username" || field == "emailaddress")
{
query.Connection = connection;
query.CommandType = CommandType.StoredProcedure;
query.CommandText = "GetUser";
var pField = query.Parameters.AddWithValue("@Field", field);
pField.Direction = ParameterDirection.Input;
var pValue = query.Parameters.AddWithValue("@Value", value);
pValue.Direction = ParameterDirection.Input;
try
{
connection.Open();
SqlDataReader _reader = query.ExecuteReader();
>>> while(_reader.Read())
{
_usuario.EmailAddress = (string)_reader["EmailAddress"];
_usuario.Username = (string)_reader["Username"];
_usuario.FirstName = (_reader["FirstName"] != DBNull.Value) ? (string)_reader["FirstName"] : string.Empty;
_usuario.LastName = (_reader["LastName"] != DBNull.Value) ? (string)_reader["LastName"] : string.Empty;
_usuario.MobileNumber = (_reader["MobileNumber"] != DBNull.Value) ? (string)_reader["MobileNumber"] : string.Empty;
}
_reader.Close();
return _usuario;
}
catch (SqlException ex)
{
Console.WriteLine("SQL Error: " + ex.Message);
}
finally
{
connection.Close();
}
}
return _usuario;
}
}
}
我有这个存储过程:
CREATE PROCEDURE [dbo].[GetUser]
@Field nvarchar(100),
@Value nvarchar(100)
AS
SELECT EmailAddress,
Username,
FirstName,
LastName,
MobileNumber,
Register_Date
FROM Users
WHERE @Field = @Value
RETURN 0
这不会返回任何东西。这不会产生异常,但是当它到达while循环时,它会跳转并结束它返回创建的对象,并且所有内容都为null。
任何线索?我试图改变存储过程,但没有运气,
答案 0 :(得分:2)
您无法在T-SQL中参数化字段。您的查询实际上将以WHERE 'someStringValue' = 'anotherStringValue'
执行,这将永远不会为真,因此永远不会返回任何字段(当然,除非您在@field = 'foo'
和@value = 'foo'
中输入 - 在这种情况下,每一行都将被退回)。
如果要将字段名称设为变量,则必须使用动态SQL。
答案 1 :(得分:1)
它没有读取任何内容,因为SQL没有返回任何内容。 @Field = @Value没有按照你的想法做到。如果分别传递'a'和'b',则查询将返回此条件为真的所有行(即0行)。
@Field只是一个变量,它不是一个关于用户的专栏(我猜)你认为它可能是。
答案 2 :(得分:0)
变量和字段名称之间存在混淆。
你不能这样做。您必须使用动态SQL。
请注意潜在的SQL注入攻击!
我建议您首先在存储过程中验证输入。
CREATE PROCEDURE [dbo].[GetUser]
@Field nvarchar(100),
@Value nvarchar(100)
AS
-- Do check @Field to prevent SQL injection !
-- IF @Field <> 'Username' or @Field <> 'id' ...
-- RAISEERROR ...
DECLARE @sql NVARCHAR(max)
SET @sql =
'SELECT EmailAddress,
Username,
FirstName,
LastName,
MobileNumber,
Register_Date
FROM Users
WHERE [' + @Field + '] = ' + @Value
EXEC sp_executesql @sql
RETURN 0
编辑:我刚刚意识到动态SQL事物已在我输入的答案中被提及。为了避免这个答案是多余的,这里有一个很好的提示,可以在不重复_reader [&#34;&#34;]的情况下处理DBNull.Value
。
_usuario.FirstName = (_reader["FirstName"] != DBNull.Value) ? (string)_reader["FirstName"] : string.Empty;
可以替换为
_usuario.FirstName = _reader["FirstName"] as string ?? string.Empty;
如果该字段是DBNull对象,则将其强制转换为字符串将导致null值。如果它发生了,一元?运算符将其转换为string.Empty。