У меня есть требование для преобразования LINQ в DataTable.
Я украл следующий Дополнительный Метод у StackOverflow:
public static DataTable ToDataTable<T>(this IEnumerable<T> items)
{
var tb = new DataTable(typeof(T).Name);
PropertyInfo[] props =
typeof(T).GetProperties(BindingFlags.Public
| BindingFlags.Instance);
foreach (var prop in props)
{
tb.Columns.Add(prop.Name, prop.PropertyType);
}
foreach (var item in items)
{
var values = new object[props.Length];
for (var i = 0; i < props.Length; i++)
{
values[i] = props[i].GetValue(item, null);
}
tb.Rows.Add(values);
}
return tb;
}
Когда таблица содержит нулевые значения, она выдает исключение. (т.е.)
DataSet does not support System.Nullable<>
Comission (Десятичный тип) столбец содержит нулевое значение),
в
tb.Columns.Add(prop.Name, prop.PropertyType);
Как зафиксировать его?
Это можно сделать с помощью команды дисплеев
.
display/i $ pc
разобрает текущую инструкцию непосредственно перед приглашением
печатается каждый раз:
(gdb) b main
Breakpoint 1 at 0x80483b5: file hw.c, line 5.
(gdb) display/i $pc
(gdb) r
Starting program: /tmp/hw
Breakpoint 1, main () at hw.c:5
5 puts("Hello world");
1: x/i $pc
0x80483b5 <main+17>: movl $0x8048490,(%esp)
Теперь выполните инструкцию (затем просто продолжайте нажимать Enter, чтобы повторить):
(gdb) si
0x080483bc 5 puts("Hello world");
1: x/i $pc
0x80483bc <main+24>: call 0x80482d4 <puts@plt>
(gdb)
0x080482d4 in puts@plt ()
1: x/i $pc
0x80482d4 <puts@plt>: jmp *0x804959c
Current language: auto; currently asm
(gdb)
0x080482da in puts@plt ()
1: x/i $pc
0x80482da <puts@plt+6>: push $0x10
(gdb)
0x080482df in puts@plt ()
1: x/i $pc
0x80482df <puts@plt+11>: jmp 0x80482a4 <_init+48>
Это все еще работает, когда мы доходим до этой точки:
(gdb)
0x080482a4 in ?? ()
1: x/i $pc
0x80482a4 <_init+48>: pushl 0x804958c
(gdb)
0x080482aa in ?? ()
1: x/i $pc
0x80482aa <_init+54>: jmp *0x8049590
(gdb)
0xb7f052d0 in _dl_runtime_resolve () from /lib/ld-linux.so.2
1: x/i $pc
0xb7f052d0 <_dl_runtime_resolve>: push %eax
Более одного выражения дисплеев
может быть активным одновременно (используйте недисплеи < число >
, чтобы удалить их). Например, чтобы посмотреть, что происходит с % eax
:
(gdb) display/x $eax
2: /x $eax = 0xbf90ab34
(gdb) si
0xb7f052d1 in _dl_runtime_resolve () from /lib/ld-linux.so.2
2: /x $eax = 0xbf90ab34
1: x/i $pc
0xb7f052d1 <_dl_runtime_resolve+1>: push %ecx
(gdb)
0xb7f052d2 in _dl_runtime_resolve () from /lib/ld-linux.so.2
2: /x $eax = 0xbf90ab34
1: x/i $pc
0xb7f052d2 <_dl_runtime_resolve+2>: push %edx
(gdb)
0xb7f052d3 in _dl_runtime_resolve () from /lib/ld-linux.so.2
2: /x $eax = 0xbf90ab34
1: x/i $pc
0xb7f052d3 <_dl_runtime_resolve+3>: mov 0x10(%esp),%edx
(gdb)
0xb7f052d7 in _dl_runtime_resolve () from /lib/ld-linux.so.2
2: /x $eax = 0xbf90ab34
1: x/i $pc
0xb7f052d7 <_dl_runtime_resolve+7>: mov 0xc(%esp),%eax
... и здесь изменение в % eax
можно увидеть:
(gdb)
0xb7f052db in _dl_runtime_resolve () from /lib/ld-linux.so.2
2: /x $eax = 0xb7f0d668
1: x/i $pc
0xb7f052db <_dl_runtime_resolve+11>: call 0xb7eff780 <_dl_fixup>
(gdb)
-121--4859617- См. также: SO 327980 .
Комитет Standard C создал технический отчет TR 24731-1 , частично по инициативе Microsoft (я полагаю). Она стандартизирует интерфейсы для различных функций, таких как vsnprintf _ s ()
. Однако, к сожалению, интерфейс, определенный стандартом, несовместим с интерфейсом, определенным Microsoft, что делает стандарт в значительной степени неактуальным.
Например, TR 24731-1 говорит, что интерфейс для vsnprintf _ s ()
является:
#define _ _STDC_WANT_LIB_EXT1_ _ 1
#include <stdarg.h>
#include <stdio.h>
int vsnprintf_s(char * restrict s, rsize_t n,
const char * restrict format, va_list arg);
К сожалению, MSDN говорит, что интерфейс для vsnprintf _ s ()
является:
int vsnprintf_s(
char *buffer,
size_t sizeOfBuffer,
size_t count,
const char *format,
va_list argptr
);
Буфер параметров
Обратите внимание, что это не просто вопрос отображения типа: количество фиксированных аргументов различно и поэтому непримиримо. Для меня также неясно (и, предположительно, для комитета по стандартам тоже), какая польза есть от того, чтобы иметь и ', и' count '; он выглядит как одна и та же информация дважды (или, по крайней мере, код обычно записывается с одинаковым значением для обоих параметров).
-121--2881570-Вот сутенерская версия:
public static DataTable ToDataTable<T>(this IEnumerable<T> items) {
DataTable table = new DataTable(typeof(T).Name);
PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in props) {
Type propType = prop.PropertyType;
// Is it a nullable type? Get the underlying type
if (propType.IsGenericType && propType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
propType = new NullableConverter(propType).UnderlyingType;
table.Columns.Add(prop.Name, propType);
}
foreach (var item in items) {
var values = new object[props.Length];
for (var i = 0; i < props.Length; i++)
values[i] = props[i].GetValue(item, null);
table.Rows.Add(values);
}
return table;
}
Edit : Немного изменил мой код, протестировал его, он работает!:)
Вы можете проверить наличие null, а затем вместо этого сохранить DBNull.Value в качестве значения. В MSDN есть статья о нулевых значениях , в которой особо подчеркивается отсутствие поддержки Nullable <> наборами данных.
Если у вас есть
values[i] = props[i].GetValue(item, null);
, сделайте это
var value = props[i].GetValue(item, null);
values[i] = value ?? ((object)DBNull.Value);