views:

125

answers:

2

I am trying to fill in a combobox on my winform app from the database. I know there is info in the DB. I know the SP works. It returns the correct ColumnNames. But the DataSet itself is empty? Help!?!?

Call from my form-->

cboDiagnosisDescription.Properties.DataSource = myDiagnosis.RetrieveDiagnosisCodes();

The RetrieveDiagnosisCodes -->

public DataSet RetrieveDiagnosisCodes()
    {
        string tableName = "tblDiagnosisCues";
        string strSQL = null;
        DataSet ds = new DataSet(tableName);
        SqlConnection cnn = new SqlConnection(Settings.Default.CMOSQLConn);
        //strSQL = "select * from " & tableName & " where effectivedate <= getdate() and (termdate >= getdate() or termdate is null)"
        strSQL = "select tblDiagnosisCues.*, tblDiagnosisCategory.Description as CategoryDesc, tblDiagnosisSubCategory.Description as SubCategoryDesc " + "FROM dbo.tblDiagnosisCategory INNER JOIN " + "dbo.tblDiagnosisSubCategory ON dbo.tblDiagnosisCategory.Category = dbo.tblDiagnosisSubCategory.Category INNER JOIN " + "dbo.tblDiagnosisCues ON dbo.tblDiagnosisSubCategory.SubCategory = dbo.tblDiagnosisCues.SubCategoryID " + "where effectivedate <= getdate() and (termdate >= getdate() or termdate is null) order by tblDiagnosisCues.Description";
        SqlCommand cmd = new SqlCommand(strSQL, cnn) {CommandType = CommandType.Text};
        SqlDataAdapter da = new SqlDataAdapter(cmd);
        try
        {
            //cnn.Open();
            da.Fill(ds);
        }
        catch (Exception ex)
        {
            throw;
        }
        finally
        {
            cmd.Dispose();
            da.Dispose();
            //ds.Dispose();
            cnn.Close();
            cnn.Dispose();
        }
        return ds;
    }

The reason I know it is returning the correct column names is that I tried the following with a DevExpress LookUpEdit box and it populates the correct columns from the DB -->

            var myDiagnosis = new Diagnosis();
        var ds = myDiagnosis.RetrieveDiagnosisCodes();
        lkuDiagnosis.Properties.DataSource = ds;
        lkuDiagnosis.Properties.PopulateColumns();
        lkuDiagnosis.Properties.DisplayMember = ds.Tables[0].Columns[1].ColumnName;
        lkuDiagnosis.Properties.ValueMember = ds.Tables[0].Columns[0].ColumnName;

Ideas? Mainly, I don't even know how to proceed tracking this down...How to debug it?

EDIT 1

Based on a comment I ran the following SQL by itself and it returned 650 results...

select tblDiagnosisCues.*, 
 tblDiagnosisCategory.Description as CategoryDesc, 
 tblDiagnosisSubCategory.Description as SubCategoryDesc 
FROM dbo.tblDiagnosisCategory 
    INNER JOIN dbo.tblDiagnosisSubCategory 
    ON dbo.tblDiagnosisCategory.Category = dbo.tblDiagnosisSubCategory.Category 
     INNER JOIN dbo.tblDiagnosisCues ON dbo.tblDiagnosisSubCategory.SubCategory = dbo.tblDiagnosisCues.SubCategoryID 
where effectivedate <= getdate() and (termdate >= getdate() or termdate is null) order by tblDiagnosisCues.Description
A: 

If the data is properly binding to another control, it indicates that there is an issue with the databinding process. What does your databinding setup look like for the combobox in question? Are all the column names properly spelled and setup?

Dillie-O
I wasn't databinding... :( I just set the datasource and then specify the Display and Value Member. Is that my problem?
Refracted Paladin
No, setting up your data source was the "databinding" process. There is no need to explicitly call a databind method like in asp.net, but it sounds like you're on the path to the right solution.
Dillie-O
+4  A: 

//cnn.open();

...

//ds.dispose();

There is no need to specify a table name in the dataset constructor. The fill method will add a table. Also no need to open the connection since the sqldataadapter will open and close the connection for you. Also, I prefer to return a datatable as opposed to dataset with one table.

The code could be refactored to the following...of coure add the try catch if you want to log the exception.

public DataTable RetrieveDiagnosisCodes()
{
    //string tableName = "tblDiagnosisCues";
    DataSet ds = new DataSet();
    Datatable dt = null;
    //strSQL = "select * from " & tableName & " where effectivedate <= getdate() and (termdate >= getdate() or termdate is null)"
    string strSQL = "select tblDiagnosisCues.*, tblDiagnosisCategory.Description as CategoryDesc, tblDiagnosisSubCategory.Description as SubCategoryDesc " + "FROM dbo.tblDiagnosisCategory INNER JOIN " + "dbo.tblDiagnosisSubCategory ON dbo.tblDiagnosisCategory.Category = dbo.tblDiagnosisSubCategory.Category INNER JOIN " + "dbo.tblDiagnosisCues ON dbo.tblDiagnosisSubCategory.SubCategory = dbo.tblDiagnosisCues.SubCategoryID " + "where effectivedate <= getdate() and (termdate >= getdate() or termdate is null) order by tblDiagnosisCues.Description";

    using(SqlDataAdapter da = new SqlDataAdapter(strSQL, Settings.Default.CMOSQLConn))
    {
      da.Fill(ds);
    }
    if (ds.Tables.Count > 0)
    {
      dt = ds.Tables[0];
    }

    return dt;
}
dotjoe
Are these General Tips for Best Practice? or a possible Solution? Thank You
Refracted Paladin
Good catch...! +1
Cerebrus
I think neither suggestions can be regarded as "best practices". Both can be regarded as developer preference. The Dataset name in the constructor the Dataset class specifies the Root element if you serialize it to XML. (rather than the default "NewDataset")
Cerebrus
general tips...but I think the ds.dispose() was the root cause.
dotjoe
@Cerebus good point. However, when all you care about is the table, it's really kind of pointless.
dotjoe
@dotjoe: just to be clear. You are saying comment out those two lines in the Finally portion and all should be good?
Refracted Paladin
@Mr_Mom Yes. Looking over the code again, the finally block executes regardless of success or failure. And the ds.dispose command is effectively flushing out all the data you just downloaded. I would agree that returning the datatable would be a better route to go. Just change "return ds" to "return ds.Tables[0]"
Dillie-O
@Dillie-O: Thanks, unfortunately commenting those lines out did not fix my problem. Also, if I just make the change you suggest I get a cannot convert DataSet to DataTable error.
Refracted Paladin
That's funny I just came on here to post my solution of changing it to DataTables. Great job everyone!! Can anyone shed any light on why a DataTable vs a DataSet works?
Refracted Paladin
I think you could use a dataset...but then you would need to set the value member and display member as "tablename.columnname" instead of just "columnname". By using a datatable your just saving the binding from having to find the table inside the dataset.
dotjoe
I'm not positive about the above comment...never tried it.
dotjoe
okay, DataTables seem to make more sense anyway as it is my understanding that DataSets are for larger sets of Data.THanks for the help!
Refracted Paladin
A DataSet is a collection of tables, relationships, keys, etc. It is a lot like a portable database, all setup for a convenient "disconnected" data model to work with. Most of the objects in the .NET framework can not databind by default to such a complex object. The DataTable, however, is a single entity (albeit with columns and rows) that most of the objects know how to bind to with little difficulty, you just have to specify the column you wish to refer to.
Dillie-O
This place never ceases to amaze me. Thank you so much.
Refracted Paladin