SharePoint 2013. Тип поля Geolocation
В SharePoint 2013 появился новый тип поля, предназначенный для работы с географическими данными. Называется он Geolocation (Geographic location that represents a point on a map). Также появился новый тип представления, предназначенный для отображения данных списка на карте.
Для отображения данных используются карты Bing Maps. В представлении списка просмотр данных осуществляется с использованием callout'ов:
А вот так в SharePoint 2013 Preview выглядит представление списка в виде карты:
Не для пользователей
В Preview версии SharePoint 2013 изначально нет возможности добавить столбец этого типа в список/библиотеку. Это связано с тем, что в SharePoint'е изначально нет такого поля. Тип поля есть, а поля такого типа нет. На MSDN есть статья о том, как добавить поле Geolocation в список программно, используя клиентскую модель SharePoint. Но этот способ, как минимум, некрасивый. Значит нужен другой.
Geolocation field solution
Чтобы реализовать поддержку типа поля Geolocation как в самом SharePoint 2013 для конечных пользователей, так и в Visual Studio 2012 для разработчиков достаточно создать крохотный sandbox solution, который будет содержать один единственный элемент - колонку типа Geolocation. Все решение укладывается в 10 строк:
- <?xml version="1.0" encoding="utf-8"?>
- <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
- <Field
- ID="{43db0e75-7489-4e6e-89d2-14c6cf26252f}"
- Name="GeolocationColumn"
- DisplayName="Geolocation Column"
- Type="Geolocation"
- Group="Geolocation">
- </Field>
- </Elements>
Развернув это решение на портале, мы получаем возможность добавлять колонки типа Geolocation в списки/библиотеки:
А также обеспечиваем доступность его в конструкторе типа содержимого в Visual Studio 2012:
Одно крохотное решение, которое можно развернуть даже удаленно (т.к. это sanbox) и никакого танца с бубном (пользоваться консольным приложениям, чтобы добавить столбец в список!)
Geolocation изнутри
В объектной модели SharePoint поле Geolocation представлено классом SPFieldGeolocation, который унаследован напрямую от SPField, т.е. не завязан ни на какие другие типы полей:
Для хранения значений в таблице dbo.AllUserData есть всего два столбца типа geography. Так что, добавив всего третий столбец такого типа в список, данные в таблице будут занимать по две строки на каждый элемент, что снизит производительность. Хотелось бы, чтобы в следующих версиях кол-во столбцов для хранения географических данных увеличилось. Таблица dbo.AllUserData теперь является wide-таблицей и содержит более 4000 столбцов! Так что пара-тройка дополнительных полей для географических данных - пустяк.
Работа с данными Geolocation
Теперь пара примеров работы с данными нового типа. В SharePoint 2013 появился новый класс, представляющий возможность работы с географическими данными - SPFieldGeolocationValue:
- var web = SPContext.Current.Web;
- var list = web.GetList("GeoLocationDemoList");
- var item = list.GetItemById(1);
- var geoVal = item["GeoField"] as SPFieldGeolocationValue;
- if (geoVal != null)
- {
- var lat = geoVal.Latitude;
- var lon = geoVal.Longitude;
- var mes = geoVal.Measure;
- var alt = geoVal.Altitude;
- }
Здесь все предельно просто. Можно задавать значения для широты (Latitude), долготы (Longitude), масштаба (Measure) и высоты (Altitude). Класс SPFieldGeolocationValue имеет полный набор конструкторов для создания нового значения поля:
- public SPFieldGeolocationValue();
- public SPFieldGeolocationValue(string fieldValue);
- public SPFieldGeolocationValue(double latitude, double longitude);
- public SPFieldGeolocationValue(double latitude, double longitude,
- double altitude, double measure);
fieldValue здесь имеет следующий формат: POINT ({Latitude}, {Longitude} [{Measure}, {Altitude}]). В таком же формате можно получить данные, вызвав метод ToString объекта SPFieldGeolocationValue.
Geolocation и Linq to SharePoint
Linq to SharePoint, начиная с 15 версии, умеет работать с geolocation полями. Это единственное нововведение в Linq to SharePoint 2013 :(. SPMetal для полей geolocation генерирует примерно следующий код:
- [Microsoft.SharePoint.Linq.ColumnAttribute(Name = "Geolocation",
- Storage = "_geo", FieldType = "Geolocation")]
- public string Geo
- {
- get
- {
- return this._geo;
- }
- set
- {
- if ((value != this._geo))
- {
- this.OnPropertyChanging("Geo", this._geo);
- this._geo = value;
- this.OnPropertyChanged("Geo");
- }
- }
- }
- private string _geo;
Т.е. данные будут представлены в виде простого текста, в вышеописанном формате. Для работы с данными можно инкапсулировать в своем классе функционал из класса SPFieldGeolocationValue.
Но есть и другой способ. Данные типа geography описаны в сборке Microsoft.SqlServer.Types.dll, которая поставляется вместе с SQL Server'ом. В моем случае она располагалась по адресу: C:\Program Files (x86)\Microsoft SQL Server\110\SDK\Assemblies. Класс для работы с данными geography называется SqlGeography, конструктор которого также умеет принимать географические данные в виде текста:
- var Geography = SqlGeography.Parse(item.Geo);
- var lat = Geography.Lat;
- var lon = Geography.Long;
Этот класс пригодится для реализации сложной логики при работе с географическими данными. Напоследок скажу, что данные geolocation фильтрации и сортировки не подлежат. Но здесь, я думаю тоже есть варианты обойти это ограничение. Об этом будет отдельный пост в скором будущем (решение задачи поиска ближайшего банкомата, например).