SqlCeServer: как хранить один символ? - PullRequest
2 голосов
/ 14 июля 2011

У меня есть столбец в моей Microsoft SQL CE 3.5 SP2 базе данных с именем Тип , который должен хранить один символ.

Для этого яотформатировал столбец как nchar(1), и хранение данных работает нормально.

Тем не менее, всякий раз, когда я пытаюсь заполнить DataTable, используя Visual Studio 2010 , Type значения столбца хранятся в виде string values.

Это действительно вызывает хаос, только когда я пытаюсь использовать один из методов нашей компании, чтобы проверить, изменилась ли данная строка данных.Значение, хранящееся в памяти (символ), равно никогда и равно значению, считанному из базы данных (поскольку это другой тип данных).

Вместо того, чтобы писать специальную процедуру, которая проверяетв каждом столбце, чтобы увидеть, является ли это тип данных char и приведение, существует ли другой тип данных SQL , который я должен назначить для столбца таблицы?

Список доступныхСтолбцы выглядят как {bigint, двоичный, битный, datetime, float, image, int, money, nchar, ntext, numeric, nvarchar, real, rowversion, smallint, tinyint, uniqueidentifier, varbinary}.

enter image description here

Решено

Чтобы определить, изменились ли мои данные In Memory из таблицы SQL CE, я использовал следующую процедуру:

// Class RowData
// private List<CellData> cellList;

public bool Changed(DataTable table) {
  int index = RowIndex(table);
  if (-1 < index) {
    DataRow row = table.Rows[index];
    foreach (DataColumn col in table.Columns) {
      if (!String.IsNullOrEmpty(col.ColumnName)) {
        bool found = false;
        foreach (var cell in cellList) {
          if (cell.ColumnName == col.ColumnName) {
            object o = row[cell.ColumnName];
            if (col.DataType != typeof(string)) {
              if (!cell.Value.Equals(o)) {
                return true; // this fails on a Char.value 'C' != "C"
              }
            } else if (col.MaxLength != 1) {
              if (!cell.Value.Equals(o)) {
                return true; // this fails on a Char.value 'C' != "C"
              }
            } else {
              string str = o.ToString();
              if (!cell.Value.Equals(str[0])) {
                return true;
              }
            }
            found = true;
          }
          if (found) {
            break;
          }
        }
      }
    }
    return false;
  }
  return true;
}

Не стесняйтесь критиковать что-либо в моем коде.Я ненавижу слышать, что не делаю что-то лучше, но это всегда стимулирует рост моих способностей.

Ответы [ 4 ]

2 голосов
/ 14 июля 2011

SQL не имеет типа данных char. Все, что у него есть, это строки & mdash; char(n), varchar(n), nchar(n) и nvarchar(n). Вы заметите, что char заметно по отсутствию на графике конверсии на http://msdn.microsoft.com/en-us/library/cc716729.aspx

Если вы используете SqlDataReader, вы можете извлечь свое значение char в виде массива символов с помощью метода GetChars() SQLDataReader:

SqlDataReader sdr = ...
...
int    ordinalColumnNumber = 3 ;
char[] buffer              = new char[1] ;
int    charCount           = sdr.GetChars( ordinalColumnNumber , 0 , buffer , 0 , buffer.Length ) ;
if ( charCount != buffer.Length ) throw new InvalidOperationException() ;
char value = buffer[0] ;

Это, вероятно, так близко, как вы собираетесь получить. Альтернативой было бы хранить ваш единственный символ как smallint. Спецификация языка C # определяет неявное преобразование из char в short или ushort, поэтому сравнение должно работать так, как вы ожидаете:

public bool Test( char value , short expected )
{
  return ( value == expected ) ;
}
1 голос
/ 17 декабря 2013

Вы всегда можете создать вспомогательный метод, основанный на коде Николасе, представленном выше.Вы просто передаете текущий объект чтения данных в качестве параметра, за которым следует столбец, который вы собираетесь запросить.

char isOkToEmailPromos = GetAChar(reader, 9); // Calling method


private char GetAChar(SqlDataReader rd, int column)
    {
        char[] value = new char[1];
        long charCount = (long)rd.GetChars(column, 0, value, 0, value.Length); 
        if (charCount != value.Length) throw new InvalidOperationException();
        return value[0];

    }
1 голос
/ 14 июля 2011

Я не думаю, что вы можете обойти преобразование NCHAR в строку.

Можете ли вы добавить свойство в модель, которая преобразует его, например,

public char CharStatus { get { return status[0]; } }

Имеет смысл ?!

1 голос
/ 14 июля 2011

Это обычное дело. Ни одна из известных мне баз данных не имеет тип с одним символом, только строки длиной 1.

Не должно быть такой проблемой, чтобы преобразовать ваш символ в строку или сравнить его с fieldValue [0].

Альтернативой является сохранение типов в качестве значений SmallInt (возможно, сопоставленных с перечислениями).

...