2010-04-23 2 views
1

В нашем приложении мы рассматриваем использование динамически генерируемых классов для хранения многих наших данных. Причина этого заключается в том, что у нас есть клиенты с таблицами, которые имеют разные структуры. Таким образом, у вас может быть таблица клиентов под названием «DOG» (только для этого), которая содержит столбцы «DOGID», «DOGNAME», «DOGTYPE» и т. Д. Клиент № 2 может иметь одну и ту же таблицу «DOG» с колонками " DOGID "," DOG_FIRST_NAME "," DOG_LAST_NAME "," DOG_BREED "и т. Д. Мы не можем создавать классы для них во время компиляции, так как клиент может изменить схему таблицы в любое время.Заполнение и использование динамических классов в C# /. NET 4.0

На данный момент у меня есть код, который может генерировать класс «DOG» во время выполнения с использованием отражения. Я пытаюсь выяснить, как заполнить этот класс из DataTable (или какого-либо другого механизма .NET) без особых штрафных санкций. У нас есть одна таблица, содержащая ~ 20 столбцов и ~ 50 тыс. Строк. Выполнение foreach по всем строкам и столбцам для создания коллекции занимает около 1 минуты, что слишком мало.

Я пытаюсь найти решение, которое слишком сложно или я на правильном пути? Кто-нибудь еще испытывал такую ​​проблему? Создание динамических классов было решением, предлагаемым разработчиком Microsoft. Если мы сможем просто заполнить эту коллекцию и эффективно использовать ее, я думаю, что она может работать.

+0

Для того, чтобы сделать заметку, клиент может получить схему таблицы «на лету», поэтому ОРМ не будет работать.Мы не можем перекомпилировать и переиздавать приложение каждый раз, когда клиент производит изменение базы данных. Однако мы не можем полагаться на DataTable, поскольку он слишком медленный с большими объемами данных. –

ответ

1

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

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

+0

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

3

Что вы пытаетесь сделать, так как в .NET 3.5 вы должны быть честными. Вероятно, вам лучше создать тип с помощью словаря <> пар ключ/значение для данных в вашей модели.

Если вы можете использовать .NET 4.0, вы можете посмотреть using dynamic and ExpandoObject. Ключевое слово dynamic позволяет создавать ссылки на действительно динамические объекты. ExpandoObject позволяет вам легко добавлять свойства и методы на лету. Все без сложной рефлексии или логики. Преимущество динамических типов заключается в том, что DLR выполняет некоторое сложное кэширование информации привязки во время выполнения, чтобы позволить этим типам быть более эффективными, чем позволяет регулярное отражение.

Если все, что вам нужно сделать, это загрузить карту данных в существующие типы, то вам следует использовать что-то вроде EntityFramework или NHibernate, чтобы обеспечить поведение ORM для ваших типов.

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

+0

Было бы неплохо использовать ORM для этого, но поскольку наши таблицы могут меняться без предупреждения, ORM не будет работать. Я рассмотрел динамические возможности .NET 4.0, но проблема в том, что мы не знаем имена свойств во время компиляции, поэтому не похоже, что динамические функции будут работать. Поправьте меня, если я ошибаюсь, пожалуйста. Мы также работаем над решением, использующим словари, но я не уверен, что он будет работать, пока мы его не попробуем. Проблема в том, как загрузить данные в наши типы, которые мы генерируем. Есть ли быстрый способ сделать это? –

+0

@Bob: Таким образом, вы должны иметь возможность сопоставлять произвольные данные из вашей базы данных в динамически классы кода. Хммм. Динамические типы могут быть не полезны сами по себе ... если бы вы могли использовать фактический динамический язык (например, Ruby или Python) - вы могли бы выполнить метапрограммирование для создания функции отображения из DataTable в пользовательский тип. Похоже, у вас уже есть код, который динамически генерирует ваши классы сущностей, да? Вы пытались использовать DataReader напрямую, чтобы заполнить его, а не использовать DataTable? Это может помочь генерировать метод Load (DbDataReader) в вашем типе для поддержки эффективной загрузки. – LBushkin

+0

Ваши предположения верны. Я думал об использовании IronPython для выполнения этой части, но пока я не дошел до этого. Я попытался использовать DataReader в образце приложения, которое я написал, чтобы проверить это, и что увеличение производительности немного, но я не думаю, что мы сможем использовать его в реальном приложении, так как наши данные извлекаются через сервис. Клиентское приложение не имеет прямого доступа к базе данных. Нам пришлось бы передавать динамические объекты поверх WCF. : -O –

1

Проверьте PicoPoco и Massive. Это Micro ORMS. (облегченные рамки ORM с открытым исходным кодом), которые вы используете, просто копируя в один файл кода в свой проект.

Massive использует объект ExpandoObject и выполняет преобразования из IDataRecord в ExpandoObject, который, как я думаю, является именно тем, что вы хотите.

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