简体   繁体   中英

How to return the datatype from a datatable in one list?

I have a datatable which gives me the columnname,datatype of the column and the maximum character length. returntype should be a list and how can i link the column name and the datatype in just one list. Please Help.

 try
        {
            List<string> tablelist = new List<string>();
            DataTable dt;
            conn.Open();
            SqlCommand cmd = new SqlCommand("SELECT column_name,data_type,character_maximum_length FROM "+ dbPropertiesobj.DBName +".information_schema.columns WHERE table_name = '"+ TableName+"' ", conn);
            SqlDataAdapter sqlda = new SqlDataAdapter(cmd);
            dt = new DataTable();
            sqlda.Fill(dt);
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                string dtrow = dt.Rows[i].ItemArray[0].ToString(); //gets only the columnname
                tablelist.Add(dtrow);
            }
            return tablelist; // need the datatype and maximum character length along with the name.
        }
        catch (Exception ex)
        {
            return null;
        }

Why not a List of 3-Tuple objects (ie Tuple with 3 values)? Not sure the exact syntax for declaring the List but each entry would be something like:

Tuple.Create(column_name, datatype, max_length)

You've got a lot of stuff going on with this code. I rewrote it completely, this is not the shortest code or even the best way to do it, but it is written to be illustrative of areas to learn more or work on.

Study up on exception handling especially, when to use it and what to use it for. Never write try blocks that swallow errors. What were you planning on doing if this method returned null? Was the table name bad? Did the connection fail? A user may or may not could fix the error, but you swallowed it. Now no one knows what it was.

Even worse possibly no one knows an error even occurred here depending on what you did with the null. NEVER swallow errors like this. Applications should fail at the points where errors occur. Be careful about returning nulls like this as well. When you return nulls and then do something else the application may fail somewhere later instead and the original error is now much harder to find and fix. You may occasionally return nulls in this style when writing frameworks. For ordinary applications it is usually not needed and almost never a good idea.

Good quality production code typically contains very little exception handling because you should use conditionals to handle anything you can anticipate. Anything you cannot anticipate you usually also cannot handle. You may have a lot of try...finally blocks that exist to clean up resources, but an application should contain very few actual try..catch blacks. Normally you let errors propagate back up the call stack to a final handler that notifies a user before the app shuts down.

The following is still not the best code you could write. I kept it as close to your original as was reasonable and eliminated some shortcuts to make it clearer. Study the differences and go from there

public class SomeClass
{

    //Use parameters rather than accessing module level properties
    private IList<ColumnInformation> GetColumnInformationForTable(string dbName, string tableName)
    {
        // Favor object oriented styles and meaningful names.  Your method does not return a list of tables
        // it returns a list of column meta data
        List<ColumnInformation> columnInformations = new List<ColumnInformation>();

        // Avoid SQL conncatenation if at all possible.  NEVER concatenate where parameters into SQL commands and NEVER EVER with single quotes.
        // Here table name requires concatenation but the select parameter TableName does not.
        string selectCmdString = "SELECT column_name,data_type,character_maximum_length FROM " + dbName + ".information_schema.columns WHERE table_name = @TableName";

        // Use parameters.  Get everything ready first, don't open connections prematurely and only wrap error prone code in try blocks.
        SqlCommand cmd = new SqlCommand(selectCmdString, conn);
        SqlParameter tableNameParameter = new SqlParameter("@TableName", tableName);
        cmd.Parameters.Add(tableNameParameter);

        // Use a DataReader since you cannot modify this data anyway.
        // This also shows an appropriate use of a try block to ensure a connection gets closed, 
        // but better yet, open your reader with the CommandBehavior set to close
        // and get rid of this try block altogether
        try
        {
            //Reconsider use of a module or global level connection.  May be better to create a new here.
            conn.Open();
            SqlDataReader reader = cmd.ExecuteReader();
            //Favor OOP styles rather than indexes and arrays and repeated calls to determine things like Rows.Count in a loop 
            while(reader.Read())
            {
                // Favor explicit member access rather than index acess.
                //YOUR HOMEWORK!  Study DataReader access and rewrite the code below to handle possible nulls in length field.  Use a method based on evaluating conditionals, DO NOT use a method based on a try block.
                ColumnInformation columnInformation = new ColumnInformation(reader["column_name"].ToString(), reader["data_type"].ToString(), (int)reader["character_maximum_length"].ToString());
                columnInformations.Add(columnInformation);
            }
            reader.Close();
        }
        finally
        {
            // The only reason to use the try is to make sure the connection gets closed here.  A better approach
            // is to use the CommandBehavior.CloseConnection option and get rid of the try finally block completely.
            // But NEVER just wrap a bunch of code in try blocks arbitrarily, swallow any errors and return a null.
            conn.Close();
        }


        return columnInformations;
    }


}

public class ColumnInformation
{
    private string _columnName;
    private string _dataType;
    private int _columnLength;

    public string ColumnName
    {
        get { return _columnName; }
    }

    public string DataType
    {
        get { return _dataType; }
    }

    public int ColumnLength
    {
        get { return _columnLength; }
    }

    public ColumnInformation(string columnName, string dataType, int columnLength)
    {
        _columnName = columnName;
        _dataType = dataType;
        _columnLength = columnLength;
    }
}

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