Соединения списков и проекции
Дата последнего изменения: 2 августа 2010 г.
Применимо к: SharePoint Foundation 2010
В этой статье
Соединения и проекции в представлениях списка
Соединения и проекции в запросах
Неявные соединения без элемента Joins
В этом разделе рассматривается использование соединений списков и проекций полей в заданных Collaborative Application Markup Language (CAML) представлениях и запросах.
Соединения и проекции в представлениях списка
Представление списка может включать поля из других списков, соединенных с основным списком. Элемент языка CAML View реализует эту функциональность посредством своих дочерних элементов Joins и ProjectedFields, которые представлены в объектной модели свойствами Joins и ProjectedFields объекта SPView. (Объект SPQuery имеет свойства с теми же именами. Дополнительные сведения см. в статье Соединения и проекции в запросах.)
Соединения списков в представлениях
Элемент Joins содержит один или несколько элементов Join. Каждый из них создает внутреннее соединение или левое внешнее соединение между двумя списками. По крайней мере одно из этих соединений должно быть соединением родительского списка представления, называемого основным, с другим списком, называемым внешним. Однако могут быть и дополнительные соединения этого внешнего списка с другим внешним списком и т. п. Количество связей в цепочке соединений не ограничено, но общее число элементов Join, независимо от того,в цепочке они или нет, не может превышать значение свойства MaxQueryLookupFields объекта SPWebApplication, содержащего основной список. Системное значение по умолчанию — восемь. Список может быть соединен сам с собой как непосредственно, так и через цепочку соединений.
Важно! |
---|
Существует несколько требований, которые необходимо учитывать при создании соединений списков. Нельзя соединять просто любые два списка, без учета их типов. Кроме того, если два списка могут быть соединены, в качестве пары полей "join on" можно использовать не любые основные и внешние поля. Поле в основном списке должно быть полем подстановки, и должно подставляться в поле внешнего списка. По этой причине все соединения отражают отношения подстановки между списками. |
Разметка в следующем примере представляет веб-сайт SharePoint Foundation, на котором находится клуб родителей, продающих друг другу бывшую в употреблении детскую одежду. Для этого сайта необходимо представление списка Orders (заказы), показывающее город и регион покупателя (клиента) и продавца (поставщика). Для реализации этого представления имеются две цепочки левых внешних соединений:
Orders (заказы) с Members (участники) с Cities (города) с States (регионы);
Orders (заказы) с Members (участники) с Cities (города).
Необходимо отметить по поводу структуры Joins следующие моменты.
Атрибут Type (тип) каждого элемента Join должен иметь значение "LEFT" или "INNER".
Поскольку имеется два соединения от списка Orders (заказы) к списку Members (участники), они должны различаться. Этого можно добиться с помощью атрибута ListAlias, который назначает списку Members псевдоним "customer" (клиент) в первом соединении и псевдоним "shipper" (продавец) во втором соединении.
Аналогично устраняется неоднозначность и для двух соединений от списка Members к списку Cities.
Не существует места, в котором какой-либо псевдоним явно назначается списку. Назначение псевдонима не обязательно, поскольку каждое соединение параллельно существующему отношению полей подстановки, и определение поля подстановки определяет внешний список.
Поля "join on" определяются парой элементов FieldRef Первый элемент представляет поле подстановки в основном списке и идентифицирует его по внутреннему имени. Его атрибут RefType должен иметь значение "Id". Если основной список в соединении не является родительским списком представления, тогда он идентифицируется с помощью атрибута List, в качестве значения которого установлен псевдоним этого списка. Второй элемент FieldRef каждой пары идентифицирует внешний список, тоже по псевдониму, и поле внешнего ключа, которое всегда должно быть полем идентификатора.
<Joins>
<Join Type='LEFT' ListAlias='customer'>
<Eq>
<FieldRef Name='CustomerName' RefType='Id'/>
<FieldRef List='customer' Name='ID'/>
</Eq>
</Join>
<Join Type='LEFT' ListAlias='customer_city'>
<Eq>
<FieldRef List='customer' Name='CityName' RefType='Id'/>
<FieldRef List='customer_city' Name='Id'/>
</Eq>
</Join>
<Join Type='LEFT' ListAlias='customer_city_state'>
<Eq>
<FieldRef List='customer_city' Name='StateName' RefType='Id'/>
<FieldRef List='customer_city_state' Name='Id'/>
</Eq>
</Join>
<Join Type='LEFT' ListAlias='shipper'>
<Eq>
<FieldRef Name='ShipperName' RefType='Id'/>
<FieldRef List='shipper' Name='ID'/>
</Eq>
</Join>
<Join Type='LEFT' ListAlias='shipper_city'>
<Eq>
<FieldRef List='shipper' Name='CityName' RefType='Id'/>
<FieldRef List='shipper_city' Name='Id'/>
</Eq>
</Join>
</Joins>
Проекции полей в представлениях
Элемент ProjectedFields создает поля из внешних списков таким образом, что они могут использоваться в представлении списка. Эти поля также должны быть идентифицированы в дочернем элементе ViewFields элемента View.
В продолжение примера с клубом родителей следующий элемент ProjectedFields создает поля для города и региона клиента и поле для города продавца. Обратите внимание на следующие моменты, связанные с этой разметкой.
Внешние списки идентифицируются по их псевдонимам, как задано в элементе Joins.
Атрибут ShowField определяет поле внешнего списка, которое используется в представлении.
Атрибут Type всегда имеет значение "Lookup". По этой причине атрибут Type не указывает тип данных поля, как это обычно бывает для элемента Field. Когда элемент Field является дочерним элементом ProjectedFields, атрибут Type просто указывает, основывается ли элемент Join (в элементе Joins, от которого зависит элемент ProjectedFields) на существующем отношении подстановки между списками. Все соединения должны основываться на существующих отношениях подстановки. См. далее список типов полей языка CAML, которые могут быть проекциями полей.
<ProjectedFields>
<Field
Name='CustomerCity'
Type='Lookup'
List='customer_city'
ShowField='Title'/>
<Field
Name='CustomerCityState'
Type='Lookup'
List='customer_city_state'
ShowField='Title'/>
<Field
Name='ShipperCity'
Type='Lookup'
List='shipper_city'
ShowField='Title'/>
</ProjectedFields>
В элемент ProjectedFields могут быть включены только следующие типы полей:
Calculated (вычисляемое поле, трактуется как обычный текст);
ContentTypeId (идентификатор типа контента);
Counter (счетчик);
Currency (денежное значение);
DateTime (дата и время);
Guid (глобальный уникальный ИД);
Integer (целое значение);
Note (примечание, только однострочное);
Number (числовое значение);
Text (текст).
Как было отмечено выше, также необходимо, чтобы поля, созданные в элементе ProjectedFields, были указаны в элементе ViewFields. Следующая структура продолжает пример.
<ViewFields>
<FieldRef Name='CustomerCity'/>
<FieldRef Name='CustomerCityState'/>
<FieldRef Name='ShipperCity'/>
</ViewFields>
Соединения и проекции в запросах
Соединения и проекции полей могут также использоваться в запросах языка CAML. В этом случае соединения и проекции полей также задаются в элементах Joins и ProjectedFields. Однако эти элементы не являются дочерними элемента Query. Они являются независимыми структурами XML, формирующими значения свойств SPQuery.Joins и SPQuery.ProjectedFields объекта SPQuery, представляющего запрос.
Обычно рекомендуется использовать поставщик LINQ to SharePoint для запроса списков SharePoint Foundation с помощью серверного кода. Поскольку язык CAML имеет элементы Joins и ProjectedFields, поставщик LINQ to SharePoint, преобразующий запросы LINQ в запросы языка CAML, может полностью поддерживать операторы LINQ join (Join в Visual Basic) и select (Select в Visual Basic). Если код предназначен для выполнения на клиенте, рекомендуется выполнять запросы с помощью Запрос SharePoint Foundation с помощью служб данных ADO.NET.
Если планируется создавать запросы языка CAML напрямую и устанавливать соответствующие свойства объекта SPQuery явно, следует подумать об использовании инструмента создания запросов. Чтобы найти такие инструменты, перейдите на сайт www.bing.com и выполните запрос "CAML query tool", не указывая кавычек. После выпуска Microsoft SharePoint Foundation 2010 может пройти некоторое время, прежде чем станут доступны какие-либо инструменты, поддерживающие создание элементов Joins и ProjectedFields.
В следующем примере показан запрос, который возвращает все заказы из списка Orders для клиентов из Лондона. В этом примере предполагается, что в списке Orders имеется поле CustomerName, смотрящее в список Customers, а в этом списке клиентов есть поле CityName, смотрящее в список городов Cities.
Для запроса необходимо соединение списка заказов Orders со списком клиентов Customers и списка клиентов Customers со списком городов Cities, поэтому значение свойства Joins может быть следующим.
<Joins>
<Join Type=’LEFT’ ListAlias=’customers’>
<Eq>
<FieldRef Name=’CustomerName’ RefType=’Id’ />
<FieldRef List=’customers’ Name=’ID’ />
</Eq>
</Join>
<Join Type=’LEFT’ ListAlias=’customerCities’>
<Eq>
<FieldRef List=’customers’ Name=’CityName’ RefType=’Id’ />
<FieldRef List=’customerCities’ Name=’ID’ />
</Eq>
</Join>
</Joins>
Поскольку раздел Where запроса проверяет город клиента, необходимо создать поле CustomerCity. В результате элемент ProjectedFields имеет следующее значение.
<ProjectedFields>
<Field
Name=’CustomerCity’
Type=’Lookup’
List=’customerCities’
ShowField=’Title’ />
</ProjectedFields>
Далее необходимо сделать это поле доступным путем добавления ссылки на него в элемент ViewFields. Таким образом, свойство ViewFields будет иметь следующее значение.
<ViewFields>
<FieldRef Name='CustomerCity'/>
</ViewFields>
Наконец, для свойства Query устанавливается следующее значение.
<Query>
<Where>
<Eq>
<FieldRef Name='CustomerCity'/>
<Value Type='Text'>London</Value>
</Eq>
</Where>
</Query>
Неявные соединения без элемента Joins
Если запрос языка CAML включает соединение списков в целях удобства чтения структуры, рекомендуется использовать явный элемент Joins. Это также обеспечит максимальную возможность того, что структура запроса будет совместима с будущими версиями SharePoint Foundation. Однако существует способ поддержки неявного соединения двух списков без использования элемента Joins. Можно создать элемент ProjectedFields, как описано выше, но дочерний элемент Field определить с атрибутом FieldRef вместо атрибута List. Атрибут FieldRef просто идентифицирует столбец подстановки в исходном списке. Кроме того, когда элемент ProjectedFields имеет атрибут FieldRef вместо атрибута List, его атрибуту Name можно назначить произвольное значение, не совпадающее со значением какого-либо столбца в исходном списке. (В этой структуре снова не требуется идентифицировать целевой список, поскольку он задан в конфигурации отношения подстановки.)
В качестве примера предположим, что имеются те же списки и отношения подстановки, что и в предыдущем разделе, а также имеется следующий запрос и элемент ViewFields.
<Query>
<Where>
<Eq>
<FieldRef Name='CustomerName'/>
<Value Type='Text'>Hicks, Cassie</Value>
</Eq>
</Where>
</Query>
<ViewFields>
<FieldRef Name='CustomerName'/>
</ViewFields>
Следует отметить, что элемент Where создает неявное соединение между списками Orders и Customers. Этот запрос необходимо поддерживать с помощью только следующего элемента ProjectedFields. Элемент Joins не потребуется. (Обратите внимание, что в качестве значения атрибута Name установлено произвольное имя, отличающееся от фактического имени столбца подстановки, заданного в атрибуте FieldRef.)
<ProjectedFields>
<Field
Name=’OrderingCustomer’
Type=’Lookup’
FieldRef=’CustomerName’
ShowField=’Title’ />
</ProjectedFields>
В этом методе также сохраняется требование существования отношения подстановки между исходным столбцом и целевым списком. Кроме того, в этом методе нельзя связывать соединения в цепочку. Например, невозможно поддерживать элемент Query, показанный в конце предыдущего раздела. Такой запрос создает неявное двойное соединение от списка заказов к списку клиентов и от списка клиентов к списку городов. Для цепочки соединений необходим явный элемент Joins.