Запись/чтение данных в поле типа int(поле может быть пустым)

Форум посвящён работе с базами данных в .NET.

Модератор: Ramzes

Thomas
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 246
Зарегистрирован: 12.11.2005 (Сб) 0:17
Откуда: "Сказочное королевство"

Запись/чтение данных в поле типа int(поле может быть пустым)

Сообщение Thomas » 16.06.2007 (Сб) 11:17

Приветствую всех.
Пишу приложение на C# работающее в БД, которая лежит на SQL 2005 сервере.
Первый класс использую для создания соединения с БД, формирования DataSet и все что с этим связано.
Второй класс использую для описания товара и формирование запросов INSERT или UPDATE.
Третий класс(форма) ввод и отображение данных. (UI)
Так вот проблема следующая.
Одно их полей таблицы, содержащей данные на товар, имеет тип данных integer, но не обязательно к заполнению.
Это значит что там может содержаться целое число или "ничего"(я так понимаю это DBNull).
Если мне надо считать или добавить запись в таблицу, где это поле заполнено, то проблем нет. Происходит нормальная конвертация значения из типа string в тип int и все. Но если в поле таблицы ничего нет или я не заполняю это поле, то Студия ругается(и совершенно обосновано) на то что невозможно конвертировать string "" в int.
Как в такой ситуации поступают грамотные люди?

Привожу для наглядности соответствующие куски кода из класса описывающего товар и класса формы.
Класс описывающий товар (сокращенный вариант, только четыре поля)
Код: Выделить всё

using System;
using System.Collections.Generic;
using System.Text;
namespace TestLuc.Classen
{
    class Artikel
    {
    #region Declaration.
        private AccessDB m_ArtikelDb;
        private string m_Code;
        private string m_Categorie;
        private string m_Naam;
        private int m_AantalMaandenGarantie;
    #endregion
    #region Constructors.
        public Artikel()
        {
            m_ArtikelDb = new AccessDB();   // экземпляр класса доступа к БД
        }
        public Artikel(string ArtCode)
        {
            m_Code = ArtCode;
            m_ArtikelDb = new AccessDB();
            FillData();
        }
    #endregion
    #region Methodes.
        //средствами первого класса соединяемся с БД и создаем ДатаСет, в нем таблицу.
        //Присваиваем значения свойствам данного класса значения из таблицы ДатаСет.
        public void FillData()
        {
            string sql = "SELECT * FROM [tblArtikels_(verkoop)]";
            sql += " WHERE [Code artikel] = '" + m_Code + "';";
            m_ArtikelDb.fillDataSet("artikel", sql);
            m_Categorie = m_ArtikelDb.DS.Tables["artikel"].Rows[0]["Categorie"].ToString();
            m_Naam = m_ArtikelDb.DS.Tables["artikel"].Rows[0]["Naam artikel"].ToString();
            m_AantalMaandenGarantie = Convert.ToInt32(m_ArtikelDb.DS.Tables["artikel"].Rows[0]["Aantal maanden garantie"]);
            // при пустом поле в таблице возникает проблема присвоения значения этому свойству (КОНВЕРТАЦИЯ).
        }
        public void Update()
        {
            string sql = "UPDATE [tblArtikels_(verkoop)] SET ";
            sql += "Categorie = '" + m_Categorie + "', ";
            sql += "[Naam artikel] = '" + m_Naam + "', ";
            sql += "[Aantal maanden garantie] = " + m_AantalMaandenGarantie;
            sql += "WHERE [Code artikel] = '" + m_Code + "';";
            m_ArtikelDb.doNonQuery(sql);
        }
        public void Insert()
        {
            string sql = "INSERT INTO [tblArtikels_(verkoop)] ([Code artikel], Categorie,";
            sql += " [Naam artikel],  [aantal maanden garantie])";
            sql += " VALUES ('" + m_Code + "', '" + m_Categorie + "', '" ;
            sql += m_Naam + "', " + m_AantalMaandenGarantie +")";
           
            m_ArtikelDb.doNonQuery(sql);
        }
    #endregion
    #region Properties.
        public string Code
        {
            get { return m_Code; }
            set { m_Code = value; }
        }
        public string Categorie
        {
            get { return m_Categorie; }
            set { m_Categorie = value; }
        }
        public string Naam
        {
            get { return m_Naam; }
            set { m_Naam = value; }
        }
        public int AantalMaandenGarantie  // С этим свойством ПРОБЛЕМА !!!
        {
            get { return m_AantalMaandenGarantie; }
            set { m_AantalMaandenGarantie = value; }
        }
    #endregion
    }
}

Класс формы
Код: Выделить всё

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace TestLuc.Artikelen
{
    public partial class frmArtNieuw : Form
    {
        public frmArtNieuw()
        {
            InitializeComponent();
        }
        TestLuc.Classen.Artikel artikel;
        private void btnToevoegen_Click(object sender, EventArgs e)
        {
            artikel = new TestLuc.Classen.Artikel();
            artikel.Code = txtArtCode.Text;
            artikel.Categorie = txtArtCat.Text;
            artikel.Naam = txtArtNaam.Text;
            artikel.AantalMaandenGarantie = Convert.ToInt32(txtArtGar.Text); // ВОТ ТУТ ПРОБЛЕМА !!!
            artikel.Insert();
            MessageBox.Show("Done");
        }
        private void btnWijzigen_Click(object sender, EventArgs e)
        {
            artikel = new TestLuc.Classen.Artikel();
            artikel.Code = txtArtCode.Text;
            artikel.Categorie = txtArtCat.Text;
            artikel.Naam = txtArtNaam.Text;
            artikel.AantalMaandenGarantie = Convert.ToInt32(txtArtGar.Text); // ВОТ ТУТ ПРОБЛЕМА !!!
            artikel.Update();
            MessageBox.Show("Done");
        }
        private void btnOpnieuw_Click(object sender, EventArgs e)
        {
            foreach (Control ctrl in this.Controls)
                if (ctrl.Name.Substring(0, 3) == "txt")
                {
                    ctrl.Text = "";
                }
        }
        private void btnSluiten_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        // поиск и отображение данных на товар по коду, ввели код - нажали Enter
        private void txtArtCode_KeyPress(object sender, KeyPressEventArgs e)
        {
            if(txtArtCode.Text!="")
                if (e.KeyChar == 13)
                {
                    string artCode = txtArtCode.Text;
                    artikel = new TestLuc.Classen.Artikel(artCode);
                    txtArtCat.Text = artikel.Categorie;
                    txtArtNaam.Text = artikel.Naam;
                    txtArtGar.Text = artikel.AantalMaandenGarantie.ToString();
                }
        }
    }
}

Всем заранее спасибо.

ЗЫ Надеюсь вопрос понятен. Надо что-то сообразить чтобы можно было записывать/считывать либо число, либо поле оставалось пустым.

ЗЫЗЫ И извиняюсь что код на Фламандском. :oops:
Met vriendelijke groetjes
VS2008 Pro FW3.5 SP1

skiperski
Идеолог
Идеолог
Аватара пользователя
 
Сообщения: 1386
Зарегистрирован: 25.06.2002 (Вт) 15:52

Сообщение skiperski » 16.06.2007 (Сб) 15:15

"0" & txtArtGar.Text

Thomas
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 246
Зарегистрирован: 12.11.2005 (Сб) 0:17
Откуда: "Сказочное королевство"

Сообщение Thomas » 17.06.2007 (Вс) 13:25

Проблему я сам решил следующим образом:
- перед присвоением значения внутренней переменной класса проверил входной обьект на DBNull.Value
Код: Выделить всё
if(m_ArtikelDb.DS.Tables["artikel"].Rows[0]["Aantal maanden garantie"]!=DBNull.Value)
         m_AantalMaandenGarantie = Convert.ToInt32(m_ArtikelDb.DS.Tables["artikel"].Rows[0]["Aantal maanden garantie"]);

- и соответственно подправил sql для Update
Код: Выделить всё

public void Update()
        {
            string sql = "UPDATE [tblArtikels_(verkoop)] SET ";
            sql += "Categorie = '" + m_Categorie + "', ";
            sql += "[Naam artikel] = '" + m_Naam + "', ";
            if (m_AantalMaandenGarantie != 0)
                sql += ", [Aantal maanden garantie] = " + m_AantalMaandenGarantie;
            else
                sql += ", [Aantal maanden garantie]= NULL";
            sql += " WHERE [Code artikel] = '" + m_Code + "';";
            m_ArtikelDb.doNonQuery(sql);
        }

- команду для INSERT тоже подправил
Код: Выделить всё

// добавлять или не добавлять поле для записи в таблицу
if (m_AantalMaandenGarantie != 0)
                sql += ", [aantal maanden garantie])";
            else
                sql += ")";
// давать заначение полю или нет
if (m_AantalMaandenGarantie != 0)
                sql += "' " + m_AantalMaandenGarantie + ")";
            else
                sql += ")";




А вообще в данном случае получается что надо каждое поле проверять на DBNull и писать соответсвующий sql-запрос, т.к.
все поля, кроме пр.ключа, могут быть Allow Nulls.
Met vriendelijke groetjes
VS2008 Pro FW3.5 SP1


Вернуться в ADO.NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7

    TopList