2012-01-27 5 views
1

Мне нравится «микро» подход Dapper, Massive, PetaPoco и т. Д., И мне нравится управлять SQL, который мы отправляем в базу данных, большую часть времени это относительно просто. Мне также нравится работать с POCO, однако, имея дело с несколько гибким дизайном схемы, вы часто сталкиваетесь с проблемами :)ORM для использования с базами данных с полугибким дизайном схемы

Предположим, у нас есть объект Person, который ВСЕГДА имеет следующие свойства.

  • Id
  • Имя
  • Email
  • Телефон

Но в некоторых случаях могут быть дополнительные свойства, такие как

  • SpecialPhoneNumber
  • VeryCustomValue

Мне бы очень хотелось, чтобы POCO с общими свойствами, которые, как мы знаем, всегда будут там. Но пусть другой доступен в коллекции ключей/ценностей.

Какой был бы лучший подход? И поддерживает ли какой-либо из упомянутых «mirco-orm's» это? Я посмотрел на них всех, но не нашел никаких признаков того, что они делают, но, может быть, я что-то упустил.

Можно ли сделать это непосредственно с помощью SqlDataReader? или будет ли производительность чтения сотен строк плохим при использовании отражения для создания объектов? У всех упомянутых орм, похоже, все хорошо, и я думаю, что использовать DataReader под ним.

Надеется, что вы можете помочь :)

EDIT: Я, вероятно, следую отметить, что мы не имеем никакого контроля над архитектурой приложения. Это ERP-решение, которое позволяет индивидуальному клиенту настраивать свое приложение и базовую базу данных. Добавление полей в приложение добавляет столбцы в базу данных. Плохо! чтобы не делать что понятно, в первую очередь

ответ

1

Massive может поддерживать это, потому что материализует данные в ExpandoObject-х:

Секрет соус является ExpandoObject. Все, что входит, и все, что выходит из Massive, - это Expando - это позволяет вам делать то, что вы хотите с ним, . В этом ядре, ExpandoObject является просто IDictionary < строки, объект>

ExpandoObject реализует IDictionary<string, Object> и IEnumerable<KeyValuePair<string, Object>>, так что вы можете перечислить и тест для членов в любом случае вам нужно.

По умолчанию Massive должен выдать запрос SELECT *, поэтому ExpandoObject будет содержать все поля в таблице, даже те, о которых вы не знаете.

Вы можете получить Massive's current code from Github.

Dapper также может выбирать динамические объекты, но в отличие от Massive, он может выбирать только данные и не может вставлять, обновлять или удалять их. EDIT: просмотр документов Dapper, похоже, он может выполнять модификации, так как он может выполнять любой sql. Существует some more recent information about performing inserts with Dapper.

+0

wow "также может выбирать динамические объекты, но в отличие от Massive он может выбирать только данные и не может вставлять, обновлять или удалять их". ничто не могло быть дальше истины. –

+0

@SamSaffron: Я не использую Dapper, и я думал, что вспомнил, когда он был изначально выпущен только для выбранных данных. Я проверил документы, когда добавил Dapper к этому ответу, и из того, что я мог сказать, это все еще так. Теперь я вижу, что он может просто выполнить любой sql, но это было несколько скрыто на странице документа. Я отредактировал свой ответ, рассмотрев ваш комментарий. –

+0

он вставляет просто отлично, из doco: http://code.google.com/p/dapper-dot-net/ «Выполнение команды, которая не возвращает результатов public static int Execute (это IDbConnection cnn, строка sql, объект param = null, транзакция SqlTransaction = null) ".. также см .: http://samsaffron.com/archive/2012/01/16/that-annoying-insert-problem-getting-data-into-the-db- using-dapper Я работаю над улучшением wiki-файла dapper, но процесс медленный –

-2

Id Имя E-mail Телефон Но в некоторых случаях могут быть дополнительные свойства, такие как SpecialPhoneNumber VeryCustomValue

Отправить архитектору назад программист школы 101. Ошибка проектирования - Телефон, SpecialPhoneNumber - это НЕ-свойства Person (которое не является Человеком, но «Entity», потому что оно также может быть юридическим лицом).

Это список «контактных точек» или что-то в этом роде.

Это говорит о том, что ведро свойств также может быть продемонстрировано в ORM с плохими характеристиками, но эй, это так, как работают базы данных sql. Плохая производительность для ведра имущества.

+1

Это просто пример, иллюстрирующий, что существуют настраиваемые свойства. Также у нас нет контроля над базовой архитектурой :) –

+0

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

+0

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

0

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

+0

Но что, если у вас нет возможности сделать это при компиляции, но вам нужна гибкость в вашем API. Чтобы вы могли получать значения для отображения, о которых вы, возможно, не знаете заранее? –

+0

@ChristianSparre, поэтому вы меняете свою схему * DB * во время выполнения? –

+1

@JoshC .: Я считаю, что сценарий OP состоит в том, что его код должен работать против множества установок базы данных - каждый из которых, возможно, был настроен путем добавления полей, которые невозможно узнать во время компиляции, и будет отличаться от установка до установки. –

0

MyBatis.NET (ранее iBatis.NET) - это инструмент отображения данных, в котором есть функция, которую я нахожу очень полезной.Если вы никогда не слышали об этом, это инструмент ORM, который позволяет вам писать SQL, и вы создаете объекты домена, и используете XML для сопоставления столбцов базы данных с свойствами объекта домена.

Одним из таких результатов отображения может выглядеть следующим образом:

<resultMap id="Contact" class="Contact" > 
    <result property="ContactId" column="ContactId" /> 
    <result property="FirstName" column="FirstName" /> 
    <result property="MiddleInitial" column="MiddleInitial" /> 
    <result property="LastName" column="LastName" /> 
</resultMap> 

В там у вас есть идентификатор результата, класс псевдоним (который отображает Namespace.Folder.Contact, например), и список от столбцов к сопоставлениям свойств.

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

<resultMap id="Person" class="Person" > 
    <result property="Id" column="Id" /> 
    <result property="Name" column="Name" /> 
    <result property="Email" column="Email" /> 
    <result property="Phone" column="Phone" /> 
</resultMap> 

И для другой ситуации:

<resultMap id="PersonExtended" extends="Person" class="Person"> 
    <!-- inherits all the "Person" result map properties --> 
    <result property="SpecialPhoneNumber" column="SpecialPhoneNumber" /> 
    <result property="VeryCustomValue" column="VeryCustomValue" /> 
</resultMap> 

И тогда вы бы два отдельных запросов, один, который выбирает только основную информацию и карты в «Человек «карта результатов» и другой запрос, который отображается на карту результатов «PersonExtended», которая содержит больше столбцов.

Существует также поддержка выбора Словари и избежания выбора N + 1. И просто для того, чтобы отметить: я не связан с проектом MyBatis, я только что нашел его действительно гибким и довольно прочным картографистом данных. Я использую его для всех своих проектов в основном потому, что написал инструмент, который может генерировать весь мой уровень доступа к данным, просто указывая его на базу данных.

Настройка его немного PITA, но, возможно, это может сработать для вас!

0

Вы можете взглянуть на динамическое отображение nHibernate.

http://ayende.com/blog/3942/nhibernate-mapping-dynamic-component

Это позволяет получить такие расширенные свойства в родовом Directory<string,object>. Таким образом, у вас есть классы с такими универсальными пакетами (словари) и динамическое расширение XML-сопоставления.

nHibernate сделает все остальное за вас.