Пользовательская функция для определения свойства «Навигация» в EF4 или прямом T-SQL - PullRequest
3 голосов
/ 21 февраля 2012

[Извинения за длинное многословное объяснение]

Я унаследовал старое приложение с базой данных SQL от (очень!) Старого продукта, и мне нужно сделать некоторые отчеты непосредственно по БД. Не совсем уверен, ПОЧЕМУ, но это структура, которую я раскрыл:

У меня есть таблица групп и таблица отчетов.

Группы имеют столбец type, 'R' или 'G', целое число numElements и столбец image с именем elements

Тип «R» означает, что группа содержит отчеты, «G» означает, что она содержит больше групп.

type = 'G'
elements = 0x2C002600
numelements = 2
result = take chunks of 4 characters, 
         reverse the last and first two character pairs to get 002C and 0026
convert hex to int to get 44 and 38

44 и 38 - два идентификатора группы - я могу проверить это из самого приложения.

То же самое относится к типу 'R', где результатом ID являются Отчеты

Есть ли способ отобразить это поведение в EF4 ИЛИ T-SQL, чтобы я мог начать делать некоторые разумные запросы? например, * * 1 022

If type = G and numElements = 3
    split the hex string into 3 chunks of 4 characters, 
    reverse character pairs, 
    convert to int, 
    map to Groups

If type = R and numElements = 11
    split the hex string into 11 chunks of 4 characters, 
    reverse character pairs, 
    convert to int, 
    map to Reports

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

Я знаю, что могу кодировать это вручную и проходить построчно и извлекать, разбивать, переворачивать, конвертировать ... но мне было интересно, если бы я мог заставить T-SQL или EF сделать это для меня?


EDIT:

Обратите внимание, что numElements является переменной, поскольку группа может содержать 1: много групп или 1: много отчетов (но не их смесь). Поэтому шестнадцатеричная строка всегда: Длина символов «0x» + «4 x numElements»

Это означает, что функция «hex to int» должна иметь возможность возвращать массив или аналогичный элемент, чтобы 1 группа могла быть связана со многими группами / отчетами.

1 Ответ

2 голосов
/ 21 февраля 2012

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

dbo.fnSplitHex(varchar hex, int chunks)  -- the actual split etc

dbo.fnSplitGHex(varchar hex) return dbo.fnSplitHex(hex, 3) -- pass 3 for chunks
dbo.fnSplitRHex(varchar hex) return dbo.fnSplitHex(hex, 11) -- pass 11 for chunks

К сожалению, вы не можете создать свойство навигации, основываясь только на этом.Однако вы можете создать представление:

  select *, dbo.fnSplitHex(..) from table1

С помощью LINQ 2 SQL я могу создать свойство навигации между представлением и другой таблицей, пока я определяю PrimaryKey для представления в модели. Не уверен с EF ... EF также

Ответ на вопрос Edit

Поскольку функция преобразования зависит от numElements , внешнего входа и не похожа на hex param, который является столбцом в основной таблице и может быть прочитан оттуда, у вас нет возможности создать NavigationProperty между основной таблицей и группами или отчетами.

К сожалению ваши проблемы не заканчиваются здесь.Будучи табличной функцией (возвращает таблицу с одним столбцом типа int), EF не может использовать ее как «компонуемую» функцию, как в следующем примере:

  from c in Groups
  from sg in fnGetIntsFromHex('G', 3, c.hex) into groups from sg in groups.DefaultIfEmpty()
  join g in Groups on sg.GroupId equals g.GroupId
  select g

Это должносоздать оператор SQL с помощью оператора CROSS APPLY, но теперь он не может этого сделать (EF 2011 г. июнь CTE может, но является CTE).

Что осталось?Я думаю, что возвращение к хранимой процедуре не такая уж плохая вещь.Другие параметры зависят от вашего набора numElements.Если этот набор ограничен разумным образом, вы все равно можете создавать виды, такие как:

create view dbo.vwSubgropus3
as
begin

select f.GroupId, f.Value = SubGroupId
from group g
where g.Type = 'G'
cross apply fnGetIntsFromHex(g.Hex, 3) f


create view dbo.vwSubgropus11
as
begin

select f.GroupId, f.Value as SubGroupId
from group g
where g.Type = 'G'
cross apply fnGetIntsFromHex(g.Hex, 11) f


create view dbo.vwReports3
as
begin

select f.GroupId, f.Value as ReportId
from group g
where g.Type = 'R'
cross apply fnGetIntsFromHex(g.Hex, 3) f
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...