How to create a list for a ComboBox that allows DB

2019-08-16 16:06发布

问题:

How to create a list for a ComboBox that allows DBNull?

I tried int? But int? is not the same as DBNull and the combobox does not work with the null value.

My datagridview combobox, needs DBNull.

I did:

var machineComboList = this.eMDataSet1.Machines.Select(row => new
            {
                Key = (int?) row.MachineID,
                Value = row.Description
            }).ToList();

int? nullValue = DBNull.Value;
machineComboList.Add(new { Key = nullValue, Value = "All" });

I want to put a DBNull value into "Key". Using int? does not work.

Related: c# combobox binding and first null value

回答1:

DBNull is only intended for ADO.NET, to make a distinction between a missing value and a null value.

int? can be null -- this is probably what you're looking for. It can never be DBNull, as they are incompatible types.

It is rare to work directly with DBNull outside of ADO.NET calls. When reading from the database, you'll usually translate it like this:

object dbValue = ...;
int? intValue = dbValue != DBNull.Value ? (int)dbValue : (int?)null;

Or if you're a little more trusting of the data types returned, you can shorten it to this:

object dbValue = ...;
int? intValue = dbValue as int?;


回答2:

This worked ... am sure there is a cleaner way

        DataTable machineComboList = new DataTable();
        machineComboList.Columns.Add("Value", typeof(string));
        DataColumn machineIdColumn = machineComboList.Columns.Add("Key", typeof(int));
        machineIdColumn.AllowDBNull = true;

        foreach (EMDataSet1.MachinesRow machineRow in this.eMDataSet1.Machines)
        {
            DataRow comboBoxDataRow = machineComboList.NewRow();
            comboBoxDataRow["Value"] = machineRow.Description;
            comboBoxDataRow["Key"] = machineRow.MachineID;
            machineComboList.Rows.Add(comboBoxDataRow);

        }

        DataRow nullComboBoxDataRow = machineComboList.NewRow();
        nullComboBoxDataRow["Value"] = "All";
        nullComboBoxDataRow["Key"] = DBNull.Value;
        machineComboList.Rows.Add(nullComboBoxDataRow);

        dataGridViewComboMachineID.DataSource = machineComboList;
        dataGridViewComboMachineID.DisplayMember = "Value";
        dataGridViewComboMachineID.ValueMember = "Key";


回答3:

DBNull.Value is not a type of integer, and it isn't actually null itself either. Instead, it is a private class which represent a null value.

You can clearly see this in the reference source. It is a public sealed class with a private constructor and a singleton (static readonly) value to it.


Typically, when you have an int?, or really, any null value, ADO.NET expects an actual value to be passed in. This is why you always see code that maps null to DBNull.Value:

using (var conn = ...)
using (var cmd = ...)
{
    cmd.Parameters.AddWithValue("@MachineId", machineId == null ? DBNull.Value : machinId);

    // ...
}

Now, on the flip side, how you want to represent null in your user interface depends on you. Thought, it doesn't really make sense to represent it with DBNull.Value, as that heavily ties your application to ADO.NET. What would happen if tomorrow you change to a different data store that wasn't sql?