Полиморфные ассоциации в .NET - PullRequest
6 голосов
/ 10 ноября 2011

Как мне эффективно / эффективно создавать полиморфные ассоциации в .NET?

При этом у меня есть несколько более детальных вопросов, которые я бы хотел видеть как часть более широкого ответа.

Технологии

  • .NET 4.0
  • ASP.NET MVC 3
  • MS SQL 2008
  • C # (последний),
  • ADO.NET Entity Framework / LINQ-to-Entities

Контекст

Я занимаюсь разработкой приложения для потребителя, состоящего из DAL, уровня бизнес-объектов, уровня брокера служб (для служб REST) ​​и, в конечном счете, веб-интерфейсов, планшетов, мобильных устройств и настольных компьютеров.

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

* 1 028 * Пример:

«Виджет А» и «Виджет Б» оба красного цвета, поэтому их можно сгруппировать в виде под «Вещи красного цвета». Однако «Widget A» - это игрушечный автомобиль, а «Widget B» - красный велосипед, поэтому , хотя оба они являются красными объектами , они являются объектами различных типов . Как таковые, они могут быть сгруппированы по-разному в других представлениях (например, «Велосипеды», которые показывают красные велосипеды, синие велосипеды и т. Д.).

Цель

Создайте эффективный уровень ядра и сервиса, который будет отзывчивым на вызывающего и легко обслуживаемым.

Что я думаю делать

Чтобы легко управлять всеми этими различными атрибутами и связями, я подумал о создании «глобальной» таблицы атрибутов, в которой атрибуты могли бы регистрироваться для объектов различных типов:

GLOBAL_ATTRIBUTES_TABLE

  1. ID (int)
  2. ObjectType (int) - таблица FK to ObjectTypes, которая содержит список типов (например, велосипед, игрушечный автомобиль и т. Д.)
  3. ObjectId (int) - идентификатор объекта в его собственной таблице (например, «Таблица велосипедов»)
  4. AttributeType (int) - таблица FK to AttributeTypes, которая содержит различные типы атрибутов (например, «Цвет», «Материал», «Возрастная группа»).
  5. AttributeId (int) - идентификатор атрибута в его собственной таблице (например, "Таблица цветов")

Таким образом, в идеале столбцы 3 и 5 (ObjectId и AttributeId) должны иметь внешний ключ динамический таблицы, соответствующий их типам.

Я думаю, что это сделает поиск быстрым, построение модели более простым и менее подробным (с точки зрения кода), упростит добавление будущих атрибутов и типов объектов, упростит обслуживание и т. Д.

Вопросы

  1. Является ли это приемлемым или хорошим методом для подражания (в отличие от создания, например, таблицы продуктов, таблицы серии и т. Д. Со списком столбцов длиной в милю)?

  2. Есть ли способ выполнить динамические внешние / полиморфные ассоциации в .NET без простого создания запроса, построения модели с результатами, запроса этой модели и т. Д .?

  3. Есть ли другие предложения по улучшению архитектуры данных?

Ответы [ 3 ]

3 голосов
/ 11 ноября 2011

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

Вместо этого я бы порекомендовал документно-ориентированную базу данных что-то вроде Raven DB или Truffler .

Если у вас есть полный контроль над машинами, на которых работает приложение, то я очень рекомендуем эластичный поиск ;он полностью распределен, реплицирован и защищен, и имеет ряд инновационных функций для отображения ваших данных, с которыми легко работать, используя HTTP и JSON (что в наши дни характерно для баз данных, ориентированных на документы, в основном из-за отсутствия схемы)of JSON).

Или, если вы хотите создать свой собственный, вы можете использовать Lucene.NET , чтобы сделать это для вас (хотя будьте осторожны, в этом случае вы не можетеразместив его в IIS, вы должны разместить его в отдельной службе из-за перезапуска домена приложения).

Во всех этих случаях вы будете хранить всю информацию, относящуюся к элементу в одном документе , поэтому взаимосвязи встроены в документ.

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

2 голосов
/ 11 ноября 2011

У меня будет отношение ObjectType / AttributeType, которое определяет, какие типы атрибутов применимы к каким типам объектов, а затем простая модель Object / Attribute.

Это должно быть соответственно абстрактно.

Object    -> ObjectType
'bicycle' -> 'vehicle'
'toy car' -> 'toy'

Attribute -> AttributeType
'red'     -> 'colour'
'39'      -> 'age'

ObjectType -> AttributeType
'vehicle' has a 'color'
'toy'     has a 'color'
'person'  has a 'age'
-- etc

Object    ->  Attribute
'bicycle' is 'red'
'toy car' is 'orange'
'Grandma' is '105'
-- etc

-- get the object types that have a color
select name from objectType where objectTypeId in
(select objectTypeId from objectTypeAttributeType where attribute = 'color')

-- get the objects that have a color
select name from object where objectTypeId in
(select objectTypeId from objectTypeAttributeType where attribute = 'color')

-- get the objects that have a color that is red
select name from object join attribute
where attribute.color = 'red'
and objectTypeId in
(select objectTypeId from objectTypeAttributeType where attribute = 'color')
0 голосов
/ 11 ноября 2011

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

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

Одним из них является сериализация некоторых атрибутов, которые не являются общими для всех объектов в строке, и помещение их в одно поле. Это хорошо, если вы точно знаете, что вам не придется фильтровать свои объекты с помощью этих атрибутов, или вам придется делать это редко (это все еще возможно с помощью правильного выражения «like», которое вы можете получить в linq, используя .Contains ).

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

...