简体   繁体   中英

How to execute a generic SQL Command in C#?

I am trying to write a Method that simply accepts a string which is an SQL Command and runs it against the pre-defined Database/Server ... This is what I have so far:

public class TSqlConnector : IDbConnector
{
    private readonly string _connectionString;

    public TSqlConnector(string conn)
    {
        _connectionString = conn;
    }
    public IEnumerable<object[]> ExecuteCommand(string query)
    {
        var res = new List<object[]>();
        try
        {
            using (SqlConnection sql = new SqlConnection(_connectionString))
            {
                sql.Open();
                SqlCommand cmd = new SqlCommand(query, sql);
                var reader = cmd.ExecuteReader();
                DataTable tbl = new DataTable();
                while (reader.Read())
                {
                    var dr = tbl.NewRow();
                    dr.ItemArray = new object[reader.FieldCount];
                    reader.GetValues(dr.ItemArray);
                    res.Add(dr.ItemArray);
                }

            }

            return res;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            throw;
        }
    }
} 

This code, however, gives me an error saying that

Input array is longer than the number of columns in this table.

I googled the error message, apparently I first have to define the DataTable's columns, using tbl.Add("ColumnName", typeof(type));

This however, completely undermines what I was trying to do - writing a generic version. All I wanted was some kind of construct which contains the information I would get from the SqlServer if I typed the same command into SSMS, I don't really care what hoops I have to jump through to read the data in C#; Using an object-Array for each row, having to manually cast each object into a string, int or whatever is perfectly acceptable, even a CSV-like string would be just fine

The only thing I don't want to do is add a definition for the table or a fixed amount of row. Each method that uses ExecuteCommand() will have to know what type of object-array is returned and that's fine but adding some complex data structure containing types and column names in addition to the SQL Commands seems like overkill.

Is there some easier way to achieve this?

What you have is an IDataReader from your cmd.ExecuteReader();

To load the results into a DataTable , you can use the Load method as follows:

var reader = cmd.ExecuteReader();
DataTable tbl = new DataTable();
tbl.Load(reader);
// now tbl contains the corresponding columns and rows from your sql command.

// Then you can return the ItemArrays from each row;

return tbl.Rows.Cast<DataRow>().Select(row => row.ItemArray);

I've used code like this to input a generic SQL query and return the results as a datatable. Of course, you'll have to parse out the results how you need them.

private DataTable QueryToTable(string sql, string cs)
{

    var ds = new DataSet();

    using (var adapter = new SqlDataAdapter(sql, cs))
    {
        adapter.Fill(ds);
    }

    return ds.Tables(0);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM