C’est avec un peu de retard, certes, mais avec beaucoup de joie que je relaye cette information: SQL Server 2012 est disponible en RC à cette adresse : Download Microsoft SQL Server 2012 Realease Candidate
Enjoy !!
Sur ce blog on discute (sans prétention!) des technologies Microsoft. Au fil des découvertes et des envies vous pourrez trouver des billets sur des sujets variés: .NET, Silverlight, SQL Server, SSIS, SSRS, WCF,...
C’est avec un peu de retard, certes, mais avec beaucoup de joie que je relaye cette information: SQL Server 2012 est disponible en RC à cette adresse : Download Microsoft SQL Server 2012 Realease Candidate
Enjoy !!
Avec l’amélioration des technologies et les nouvelles Interfaces Homme/Machine, il est intéressant de pouvoir présenter l’information sous une autre forme que la forme, historique, textuelle.
Dans cet article, l’objectif est de présenter, de bout en bout, comment localiser géographiquement des données sur une carte à partir d’un mobile Windows Phone 7. Pour ce faire, nous utilisons l’API Bing Maps pour Windows Phone 7.
En début d’année scolaire, j’ai rédigé un petit article. Et je n’ai jamais pris le temps de le publier. Je me suis fait violence et j’ai publié la première partie le mois dernier. Voici donc la suite.
Ce deuxième volet se concentre plus sur l’interaction avec WP7 et Bing Maps.
Nous avons une liste de points d’intérêts, classés par type, que nous souhaiterions afficher sur une carte géographique (Bing Maps).
http://developer.windowsphone.com/windows-phone-7/
Créer une clé de développement sur le site Bing Maps grâce à votre LiveId.
https://www.bingmapsportal.com/
Entity Framework 4 ne supportant pas le type SqlGeography, il faudra absolument utiliser une version « textuelle » des points géographiques. Pour ce faire :
· soit il est nécessaire de faire une conversion de données en utilisant l’instruction T-SQL .STAsText() (ex : MonChamp.STAsText()).
· soit il est nécessaire de faire cohabiter à la fois la donnée sous forme géographique et à la fois la donnée sous forme de string. C’est-à-dire avoir un champ de type geography, avoir un champ de type varchar pour la latitude et avoir un champ de type varchar pour la longitude.
Dans cet article, nous avons fait le choix de passer par une vue SQL pour plusieurs raisons :
· EF4 verra cette vue sous forme d’entité, ce qui facilitera son utilisation et sa manipulation entre les couches plutôt que de manipuler un « type complexe » issu d’une procédure stockée.
· On ne duplique pas la donnée de type geography. On ne fait que la convertir.
CREATE VIEW [dbo].[v_PointInteret]
AS
SELECT ID, osm_id, name, type, Position_Geo.STAsText() AS Position_Geo
FROM dbo.PointInteret
Avant de créer le modèle de données EF4, nous allons créer le projet qui contiendra ce modèle.
1. Créer un projet du type WCF Service Application
2. Créer un répertoire Data et ajouter un nouvel élément au projet de type ADO.NET Entity Data Model :
1. Une fois le modèle de données implémenté, il va falloir ajouter un élément de type WcfDataService au projet.
2. Supprimer l’élément Service1.svc de type WCF Service créé par défaut lors de la création du projet.
3. Et renommer le fichier IService1.cs en IServicePOIViewer.cs.
Cela doit donner l’arborescence suivante :
4. Nous allons maintenant implémenter le service en écrivant le code suivant dans le fichier WcfDataServicePOIViewer.svc.cs :
A la ligne 12, nous avons donné le type de notre DataModel.
Aux lignes 17 et 18, nous affectons des droits d’accès aux ressources exposées. Ici, nous donnons des droits sur tous les EntitySet et toutes les opérations de service grâce aux « * » ;
A la ligne 23, nous définissons une opération de service. Une opération de service est une méthode exposable via un service WCF Data Services.
« Les opérations de service sont annotées par l'attribut [WebGet] pour celles adressables via une requête HTTP GET et par l'attribut [WebInvoke] pour celles adressables via une requête HTTP POST.
Des paramètres de type simple uniquement peuvent être spécifiés pour les opérations de service. Celles-ci peuvent retourner void (Nothing en VB.NET), IEnumerable, IQueryable, une entité du modèle de donnée ou un type primitif. Retourner IQueryable permet de supporter des options de requête (pagination, filtre, etc.) et de naviguer via les propriétés de navigation des entités retournées. »
Source : http://badger.developpez.com/tutoriels/dotnet/odata-wcf-data-services/
5. Nous allons maintenant modifier le code du fichier IServicePOIViewer.cs pour définir le contrat de l’opération de service créée.
6. Vérifier la bonne marche du service :
http://localhost/BSE.POIViewer.Service/WcfDataServicePOIViewer.svc/Types http://localhost/BSE.POIViewer.Service/WcfDataServicePOIViewer.svc/GetPOIs?typeOfPOI='zoo'
Pour plus de détails sur ce type d’URL : http://msdn.microsoft.com/fr-fr/library/dd728279.aspx .
1. Ajouter un projet du type Windows Phone List Application
2. Ajouter les références suivantes au projet :
· Microsoft.Maps.MapControl.Common.dll
· Microsoft.Maps.MapControl.dll
· System.Windows.Browser.dll
· System.Data.Services.Client.dll
3. Créer un répertoire « Classes » dans lequel nous mettrons les différentes classes que nous créerons.
4. Générer le proxy client du service :
DataSvcutil.exe /uri:http://localhost/BSE.POIViewer.Service/WcfDataServicePOIViewer.svc/ /DataServiceCollection /Version:2.0 /out:C:\wcf\WcfDataServicePOIViewer.cs
(DataSvcutil.exe se situe dans C:\Windows\Microsoft.NET\Framework\v4.0.30319)
5. Ajouter la classe générée au projet.
6. Le Binding et le ViewModel sont déjà générés. Nous allons nous appuyer dessus en le modifiant un peu pour répondre à notre besoin.
7. Créer la classe ItemLocation:
8. Ouvrir le fichier MainViewModel.cs et supprimer la méthode SampleMethod()
9. Renommer la propriété sampleProperty en SelectedTypeOfPOI
10. Créer la propriété privée suivante :
private POIViewerDataModelcnx _context;
11. Créer la collection suivante :
public ObservableCollection<ItemLocation> Locations { get; private set; }
12. Créer la méthode suivante pour récupérer la liste des types de POI :
13. Créer la méthode suivant pour vider la collection Locations :
14. Créer les deux méthodes suivantes pour récupérer la liste des points d’intérêt :
La première exécute une requête. La deuxième traite le résultat de la requête obtenu de façon asynchrone.
15. Remplacer le corps du constructeur MainViewModel() par le suivant :
A cette étape, si vous lancez l’application, vous devriez déjà avoir une première page listant les types de point d’intérêt.
Pour éviter d’avoir des espaces entre les lignes, il suffit de mettre en commentaire la ligne 39 du fichier MainPage.xaml
A la ligne 26, vous pouvez écrire le nom de votre application dans l’attribut Text. A la ligne 27, vous pouvez écrire le nom de la liste qui est affichée, dans l’attribut Text également.
Nous allons maintenant nous occuper de la deuxième page : la page de détails. Elle sera affichée lorsqu’on sélectionne un type de point d’intérêt.
7. Pour la partie graphique, le XAML, ouvrons le fichier DetailsPage.xaml et modifions le XAML pour qu’il soit identique à celui-ci :
A la ligne 9, nous rajoutons un lien vers l’assembly fournit par Bing Maps qui nous permettra d’utiliser le fameux control Bing Maps.
A la ligne 18, nous définissons la manière dont chaque Point d’intérêt va être affiché. Ici nous utilisons des contrôles PushPin tout simple. Ce contrôle est fourni par l’API de Bing Maps.
A la ligne 34, nous modifions le titre de la page dans l’attribut Text.
A la ligne 35, nous modifions le binding pour pointer vers la propriété SelectedTypeOfPOI. Cela permettra de se souvenir de quel type de point d’intérêt nous avons sélectionné.
Enfin, à la ligne 40, nous mettons en commentaire le TextBlock qui était généré, pour insérer notre contrôle Bing Maps :
· L’attribut NavigationVisibility permet de masquer ou d’afficher la barre à outil noire, de zoom et de déplacement sur la carte.
· L’attribut Mode permet de définir le type de vue que l’on souhaite avoir en fond de carte : vue du relief, nom des villes et routes, ect…
· L’attribut Center permet de positionner la vue d’arrivée sur la carte. Ici nous ciblons la France.
· L’attribut ZoomLevel permet de zoomer sur la France plutôt que de rester trop élevé dans la vue de la carte.
· L’attribut CredentialProvider doit contenir la clé de développement que vous avez précédemment créée sur le site de Bing Maps.
A la ligne 44, nous affectons le binding à la collection des objets de type ItemLocation du ViewModel en spécifiant que le rendu devait se faire grâce au template POITemplate.
8. Pour le code de la page, modifiez l’évènement OnNavigatedTo :
Rappel : Dans cet article, nous nous appuyons au maximum sur ce qui est généré.
Vous devriez maintenant voir apparaitre une liste de point d’intérêt sur une carte de la France :
Je tiens à remercier Lionel et Franck pour leur aide dans la réalisation du prototype de cet article.
Lionel LIMOZIN http://www.paslatek.net/
Franck LIZZI http://dotnet.over-blog.fr/
Pro Silverlight 4 in C#
Pro Entity Framework 4.0
Programming Entity Framework
Learning Windows Phone Programming
http://msdn.microsoft.com/fr-fr/library/cc668792.aspx
http://developer.windowsphone.com/windows-phone-7/
http://www.microsoft.com/maps/
http://msdn.microsoft.com/en-us/library/ff941093(VS.92).aspx
http://www.microsoft.com/maps/isdk/silverlight/#MapControlInteractiveSdk.Tutorials.ShowMap.ShowMapWithCulture
Avec l’amélioration des technologies et les nouvelles Interfaces Homme/Machine, il est intéressant de pouvoir présenter l’information sous une autre forme que la forme, historique, textuelle.
Dans cet article, l’objectif sera de présenter, de bout en bout, comment localiser géographiquement des données sur une carte à partir d’un mobile Windows Phone 7. Pour ce faire, nous utiliserons l’API Bing Maps pour Windows Phone 7.
En début d’année scolaire, j’ai rédigé un petit article. Et je n’ai jamais pris le temps de le publier. Voici chose faite avec cette première partie.
Pour les données géographiques, il existe plusieurs possibilités dépendantes en partie de votre besoin:
· Soit il s’agit d’une base de données métier, dans laquelle vous avez déjà des données géographiques au format texte. La plupart du temps, il s’agit de deux colonnes (Latitude et longitude) au format varchar. Il vous suffira donc de créer une colonne de type geography et de renseigner celle-ci à l’aide des colonnes textes en faisant une conversion. Les étapes nécessaires pour effectuer cette conversion sont présentées au chapitre Comment convertir ses latitudes/longitudes en type geography
· Soit il s’agit d’une base dans laquelle vous avez déjà des données géographiques, mais vous souhaitez pouvoir superposer à ces données des territoires par exemple. Ceci afin de mieux visualiser vos données sur des fonds de cartes notamment. Les étapes nécessaires pour réaliser ce besoin sont présentées au chapitre Comment importer des données géographiques externes?
Le système géodésique le plus utilisé dans le monde est le WGS 84 (World Geodesic System of 1984). Ce système permet de placer des coordonnées sur le globe terrestre. Pour qu’un point puisse être placé de façon présente en utilisant ce système, il doit avoir un format bien particulier.
L’exemple suivant part du principe que les coordonnées géographiques qui sont à notre disposition sont au format dit « décimal ».
Etape1 : Ajouter la colonne de type geography
ALTER TABLE [dbo].[AGENCE] ADD [Position_Geo] GEOGRAPHY
Etape 2 : Alimenter cette colonne
Dans la vraie vie, les latitudes et longitudes ne sont jamais toutes renseignées correctement. Il faut donc faire attention à ne pas prendre les champs NULL par exemple. Au-delà des données NULL, il faudra faire attention à tous les enregistrements pour lesquels il y a une faute de frappe, etc.…
Exemple de données telles qu’on peut les voir chez un client :
Pour cet exemple la requête permettant d’alimenter la colonne Position_Geo sera la suivante :
UPDATE [dbo].[AGENCE]
SET [POSITION_GEO] = geography::STPointFromText('POINT(' + CAST([LONGITUDE] AS VARCHAR(20)) + ' ' + CAST([LATITUDE] AS VARCHAR(20)) + ')', 4326)
where LONGITUDE is not null
and LONGITUDE <> ''
and LATITUDE is not null
and LATITUDE <> ''
and LATITUDE like '%.%'
and LONGITUDE like '%.%'
and LONGITUDE not like '%E9%'
and LONGITUDE not like '%''%'
and LONGITUDE not like '%°%'
and LATITUDE not like '%:%'
Dans cette requête la clause WHERE nous permet de ne sélectionner que les lignes dont les coordonnées sont:
· Différentes de NULL
· Différentes de vide
· Notées sous forme décimales et non DMS (Degrés Minutes Secondes). Si vous avez des coordonnées sous cette forme 43°16'56.70"N , 5°36'7.45"E, il faut alors les convertir préalablement au format « décimal » en appliquant la règle de calcul suivante :
Degrés + (Minutes / 60) + (Secondes / 3600) = Degrés sous forme décimale
Etape 3 : Le résultat
Notez que le format geography stocke les données sous forme binaire.
Il existe un certain nombre de sources qui mettent à disposition des données géographiques sous forme de shapefile. Un shapefile est un format de fichier issu du monde des Systèmes d'Informations Géographiques (SIG) contenant toute l'information liée à la géométrie des objets décrits, qui peuvent être des points, des lignes ou des polygones.
Shape2SQL est un outil gratuit permettant d’importer facilement dans une base MS SQL Server 2008 ce type d’information géographique : http://www.sharpgis.net/page/Shape2SQL.aspx .
Pour réaliser cet article nous nous sommes basés sur un shapefile contenant des points d’intérêts (parc, zoo, restaurant,…). Ce shapefile peut être téléchargé depuis la page suivante : http://www.mapcruzin.com/free-france-arcgis-maps-shapefiles.htm. Les données ont été importées en utilisant l’outil Shape2SQL. La table issue de cet import est la suivante :
Une autre table a été créée pour les besoins de l’article : une table Type, qui contient l’ensemble des types de point d’intérêt possible.
CREATE TABLE [dbo].[Type](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Libelle] [varchar](100) NULL
) ON [PRIMARY]
INSERT INTO [dbo].[Type]
select distinct Type from dbo.PointInteret order by Type
Plusieurs sites mettent à disposition des ressources contenant différent type de données (géographiques, topographiques, etc…), parfois gratuitement. Mais ce n’est pas l’objet de cet article.
Autre exemple de ressource disponible, la carte du monde représentant les frontières des pays du globe : http://www.beginningspatial.com/world_borders_dataset . Cette fois-ci, c’est un fichier plat contenant les instructions SQL permettant de générer une table représentant les frontières de tous les pays du monde. Nous nous servirons de ces données dans notre exemple au chapitre Comment requêter les données géographiques ?
Point : Un point est une représentation exacte, définie grâce à un X et un Y. Il peut également y avoir une élévation Z et une mesure M.
LineString : Segment représentant le chemin le plus court entre deux ou plusieurs points. Si le point de départ est le même que le point d’arrivée, on parle de « ring ».
Polygon : Forme géométrique fermée, possédant une aire. Un polygon peut être « creux » en son centre grâce au retranchement d’un autre polygone en son sein.
Collection : C’est similaire à une collection en .Net. Cela contient plusieurs instances des objets précités. Les collections MultiPolygon, MultiLineString et MultiPoint, elles, comme leur nom l’indique, ne peuvent contenir que des objets d’un type bien particulier.
La requête suivante ramène tous les points d’intérêt de type zoo. On constate que les données géographiques sont stockées sous forme binaire et qu’on doit les convertir grâce aux fonctions existantes pour les rendre lisible.
select *, Position_Geo.STAsText() as WKT from PointInteret where type = 'zoo'
Outre la vue tabulaire, SSMS propose une vue du résultat sous forme spatiale. L’onglet « Spatial Results » permet donc de visualiser le résultat sous un rendu beaucoup plus fun et sexy qu’un tableau.
On peut également combiner les résultats de requêtes pour faire se superposer plusieurs résultats, à la manière de calques. Prenons par exemple la requête suivante, qui va permettre de visualiser les points d’intérêts de type zoo sur une carte géographique du monde délimitant les frontières.
SELECT Position_Geo.STAsText() AS WKT FROM PointInteret WHERE type = 'zoo'
UNION ALL
SELECT geog FROM World_Borders
Nous ne pouvons pas toutes les citer et ce n’est pas le but, mais il existe nativement des fonctions permettant de manipuler ces données géographiques afin de réaliser des opérations de :
· Conversion (ex : STAsText())
· Agrégation (ex: STDijoint(),STContains())
· Mesure (ex: STDistance(), STLength())
Par exemple la requête suivante permet de récupérer la liste des cinq zoos les plus proches du zoo de la Barben :
SELECT top 5 *, Position_Geo.STAsText()AS WKT,
Position_Geo.STDistance((select Position_Geo.STAsText() from PointInteret where name = 'Zoo de la Barben')) AS Distance
FROM PointInteret
WHERE type = 'zoo'
and name <> 'Zoo de la Barben'
order by 7
Beginning Spatial with SQL Server 2008
http://msdn.microsoft.com/en-us/library/bb933790.aspx
http://www.microsoft.com/sqlserver/2008/en/us/spatial-data.aspx
http://207.46.19.254/france/serveur/sql/donnees-geospatiales/donnees-geospatiales.mspx
Pour définir les valeurs disponibles d’un paramètre dans un rapport, Reporting Services 2008 ne vous propose que de définir des valeurs fixes ou de récupérer le résultat d’une requête sur une source de données.
Néanmoins, si vous avez du code métier un peu “touchy” qui lui seul serait capable de remonter la liste des paramètres disponibles, grâce aux expressions, vous pouvez le faire.
Pour ce faire:
Votre méthode .Net de votre code custom doit renvoyer une chaine de caractère correctement formatée pour pouvoir être “splittée” par la suite.
public string GetListeAgence()
{
return "test,test1,test2";
}
Ensuite via les propriétés du paramètre ciblé, il vous suffit de créé une expression qui appelle votre méthode et split la chaine obtenue.
=Split(Code.MyCustomCodeNonSigne.GetListeAgence(),",")
Et voila le résultat:
A partir des propriétés d’un rapport, Reporting Services vous permet d’écrire des fonctions, en VB.NET uniquement pour le moment.
Mais Reporting Services, permet aussi, fort heureusement, de référencer des assemblys métier afin d’en exploiter les fonctionnalités.
Pour ce faire, il suffit de référencer une dll dans le rapport que vous ciblez.
Il vous faut également instancier un objet de votre classe que vous souhaitez utiliser. Si c’est une classe instanciable bien évidemment: pas besoin d’objet dans le cas de méthodes statiques.
Attention : “Class Name” = Namespace.NomDeLaClasse
Pensez à ajouter votre DLL ou dans les répertoires suivants pour pouvoir tester votre rapport sous Visual Studio et utiliser votre rapport dans Report Manager:
C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies
C:\Program Files\Microsoft SQL Server\MSRS10.SQLSERVER2008\Reporting Services\ReportServer\bin
Vous pouvez également déployer votre DLL dans le GAC en la signant, mais vous aurez certainement un problème droit.
Il suffit ensuite d’appeler vos méthodes en utilisant les expressions (Code.MonObjet.MaMethode()):
La colonne CustomCode contient l’expression suivante :
=Code.MaClasseInstanciee.Addition(Fields!ID1.Value ,Fields!ID2.Value)
On additionne les colonnes ID1 et ID2. Bien entendu votre code métier sera certainement bien plus compliqué et fera certainement appel plus en profondeur aux capacité du Framework .NET.
Le résultat (mes colonnes ID1 et ID2 ont des valeurs fixes. Il est donc normal que le résultat se répète) :