实体框架 - 获取标量

时间:2017-09-13 16:08:51

标签: c# entity-framework stored-procedures

我正在尝试创建一个GetScalar方法。我们在遗留系统中使用了大量DataTable。我正在将它们转换为EF。

这是目标。这是一个简单的方法,它接受存储过程名称和参数,然后返回结果集的第一行,第一列。

public object GetScalar(string command, CommandType type = CommandType.StoredProcedure, List<SqlParameter> parameterList = null)
    {
        try
        {
            using (var cnn = new SqlConnection(ConnectionString))
            {
                using (var cmd = new SqlCommand(command, cnn))
                {
                    cmd.CommandType = type;

                    if (parameterList != null)
                    {
                        foreach (var p in parameterList)
                        {
                            cmd.Parameters.Add(p);
                        }
                    }

                    cmd.Connection.Open();
                    object obj = cmd.ExecuteScalar();
                    cmd.Connection.Close();
                    cmd.Parameters.Clear();
                    return obj;
                }
            }
        }
        catch (Exception ex)
        {
            Logging.LogError(ex, "MSSqlUtility.GetScalar");
            return -1;
        }
    }

我想在EF中使用类似的方法。这是我到目前为止所做的,但这会返回所有列 - 而不仅仅是第一列。

protected T SelectScalar<T>(string inStoredProcedure, ICollection<SqlParameter> inParameters = null)
    {
        T result = default(T);
        if (inParameters != null && inParameters.Count > 0)
        {
            string paramNames = string.Join(",", inParameters.Select(parameter => parameter.ParameterName).ToList());
            string sqlString = inStoredProcedure + " " + paramNames;
            object[] paramValues = inParameters.Cast<object>().ToArray();               
            result = Database.SqlQuery<T>(sqlString, paramValues).FirstOrDefault();
        }
        else
        {
            result = Database.SqlQuery<T>(inStoredProcedure).FirstOrDefault();
        }

        return result;
}

示例用法。这将返回一个字符串对象 - “John Doe”。

public string GetUserName(string employeeID)
    {
        if (string.IsNullOrWhiteSpace(employeeID))
        {
            return string.Empty;
        }

        var parameters = new Collection<SqlParameter>();            
        parameters.Add(StoredProcedureParameterBuilder.StringParam("@EmployeeID", employeeID, 20));
        return this.SelectScalar<string>("dbo.GetUserName", parameters).Trim();
    }

SQL查询看起来像这样:

SELECT 
    FirstName + ' ' + Last Name
,EmployeeID
FROM Users

更改存储过程不是一个选项 - 我们在其他上下文中需要两个列。当前代码返回名称和ID 。我只想获取我的查询可能吐回来的第一列第一行。

1 个答案:

答案 0 :(得分:0)

结束了必须做更多的手工工作。如果有人有更好的解决方案,我会全力以赴,但这适用于我的用例:

    /// <summary>
    /// Selects the first item in the query's result.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="inStoredProcedure">The in stored procedure.</param>
    /// <param name="inParameters">The in parameters.</param>
    /// <returns>The first object in the specified type T.</returns>
    protected T SelectScalar<T>(string inStoredProcedure, ICollection<SqlParameter> inParameters = null)
    {            
        using (System.Data.IDbCommand command = Database.Connection.CreateCommand())
        {
            try
            {                   
                command.CommandText = inStoredProcedure;
                command.CommandTimeout = command.Connection.ConnectionTimeout;

                if(inParameters != null &&  inParameters.Count > 0)
                {
                    string paramNames = string.Join(",", inParameters.Select(parameter => parameter.ParameterName).ToList());
                    command.CommandText += " " + paramNames;
                    foreach (var param in inParameters)
                    {
                        command.Parameters.Add(param);
                    }
                }

                Database.Connection.Open();
                return (T)command.ExecuteScalar();
            }
            finally
            {
                Database.Connection.Close();
                command.Parameters.Clear();
            }
        }
    }