-----------------------------------

Acquista i software ArcGIS tramite Studio A&T srl, rivenditore autorizzato dei prodotti Esri.

I migliori software GIS, il miglior supporto tecnico!

I migliori software GIS, il miglior supporto tecnico!
Azienda operante nel settore GIS dal 2001, specializzata nell’utilizzo della tecnologia ArcGIS e aderente ai programmi Esri Italia Business Network ed Esri Partner Network

-----------------------------------



Visualizzazione post con etichetta Linq. Mostra tutti i post
Visualizzazione post con etichetta Linq. Mostra tutti i post

sabato 30 aprile 2011

LINQPad: Linq ma non solo ...

LINQPad, per chi non lo conosce, è un utilissimo programma che permette di interrogare interattivamente i database mediante LINQ.

LINQPad supporta c# 4.0 ed il framework 4.0:
• LINQ to Objects
• LINQ to SQL e Entity Framework
• LINQ to XML
• Parallel LINQ

E' possibile inoltre interrogare
• OData / WCF Data Services
• SQL Azure, SQLite and MySQL Enterprise Server
• Microsoft StreamInsight
• Microsoft Dynamics CRM
• Mindscape LightSpeed ORM
• Persino il 'vecchio' SQL

LINQPad è fornito anche di moltissimi esempi per imparare LINQ.

Inoltre permette di eseguire istantaneamente espressioni, blocchi di codice o programmi con formattazione dell'output. Questo ti consente di evitare di crearti numerosi progetti di console application per testare le tue espressioni.

LINQPad è free e può anche essere eseguito senza essere installato. La funzione di autocompletamento è invece a pagamento, ma ad un costo molto contenuto.

Innanzitutto, l'interfaccia utente è il client che può interfacciarsi a più server. Per ogni query LINQPad crea un separato server; questa classe è eseguita in un suo proprio dominio di applicazione ed esegue la query in isolamento. Tale isolamento evita che interferisca con altre query e con la UI e consente a LINQPad di assicurare un annullamento della query (mediante un abort del thread) senza influenzare altri domini di applicazione.



LINPad compila le query utilizzando NET's CSharpCodeProvider o VBCodeProvider (in funzione del linguaggio che si utilizza).
Poichè c# e vb sono tipizzati staticamente, oggetti del database ai quali facciamo riferimento, necessitano di DataContext tipizzati. LINQPad, per un discorso di prestazioni, crea dataContext tipizzati al volo utilizzando Reflection.Emit piuttosto che generare e compilare il codice. E' usato LINQ to SQL rispetto a EF perchè il primo è di un ordine di grandezza nella creazione del metamodello quando è istanziato.

Vediamo qualche esempio:

dopo aver effettuato la connessione al nostro database, possiamo fare la nostra interrogazione e vedere immediatamente i risultati.


vedere la relativa forma lambda

vedere la relativa forma SQL

e l'IL


In questo caso vediamo un esempio di LINQ to Objects:


Qui vediamo un esempio utilizzando IronPython. Occorrerà far riferimento preventivamente agli assembly opportuni. Cliccando il tasto F4 si potranno aggiungere gli assembly e i namespace da utilizzare





Vediamo un esempio utilizzando la nuova classe ExpandoObject del framework 4.0



Ma LINQPad mette anche a disposizione alcune sue funzioni per, ad esempio, visualizzare immagini, visualizzare un testo html ecc.
In questo caso vediamo una chiamata alle api chart di google:
http://chart.apis.google.com/chart?cht=p3&chd=s:Uf9a&chs=350x140&chl=January|February|March|April"


Vediamo ora una interrogazione OData / WCF Data Services utilizzando stackoverflow. Nel caso di stackoverflow la chiamata è del tipo è  http://data.stackexchange.com/%3Ccommunity%3E/atom
Clicchiamo su add connection








Infine vediamo l'utilizzo di una libreria ESRI. nel caso specifico la ESRI.ArcGIS.SOESupport.dll:







Qui potete vedere come interrogare twitter

Con la versione beta corrente di LinqPad è possibile aggiungere i propri visualizzatori personalizzati.
Per maggiori dettagli vedete qui.

Qui vediamo un semplice esempio che ho realizzato:


using System;
using System.Globalization;
using System.Text;
using LINQPad;
 
namespace StudioAT.LinqPad
{
    public class Point
    {
        private double x;
        private double y;
        
        private Point()
        {
 
        }
        public Point(double x, double y)
        {
            this.x = x;
            this.y = y;
        }
 
        public double X
        {
           get 
           {
              return this.x;
           }
        }
 
        public double Y
        {
            get
            {
                return this.y;
            }
        }
    }
 
    public static class Extensions
    {
        /// <summary>
        /// Map Mode of Map Control (Microsoft)
        /// </summary>
        public enum MapMode
        {
            /// <summary>
            /// map mode road
            /// </summary>
            Road,
 
            /// <summary>
            /// map mode aerial
            /// </summary>
            Aerial,
 
            /// <summary>
            /// map mode aerial with labels
            /// </summary>
            AerialWithLabels,
 
            /// <summary>
            /// Bird's eye
            /// </summary>
            Birdseye,
 
            /// <summary>
            /// Bird's eye with labels
            /// </summary>
            BirdseyeWithLabels
        }
 
        public static void DisplayBirdsEye(this Point point)
        {
            
            string url = string.Format("http://dev.virtualearth.net/embeddedMap/v1/ajax/{0}?"Enum.GetName(typeof(MapMode), MapMode.BirdseyeWithLabels));
            string pointXY = string.Format("{1}_{0}", point.X.ToString(Helper.CultureInfoUS), point.Y.ToString(Helper.CultureInfoUS));
            string currentCulture = CultureInfo.CurrentUICulture.Name;
            Helper.GetCultureMapControl(ref currentCulture);
 
            UriBuilder uriBuilder = new UriBuilder(new Uri(url));
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("zoomLevel={0}", 10);
            sb.Append('&');
            sb.AppendFormat("center={0}", pointXY);
            sb.Append('&');
            sb.AppendFormat("pushpins={0}", pointXY);
            sb.Append('&');
            ////The heading is represented in geometric degrees with 0 or 360 = North, 90 = East, 180 = South, and 270 = West.
            ////sb.AppendFormat("heading={0}", 0);
            ////sb.Append('&');
            sb.AppendFormat("culture={0}", currentCulture);
            uriBuilder.Query = sb.ToString();
 
            System.Windows.Forms.WebBrowser wb = new System.Windows.Forms.WebBrowser() { ScriptErrorsSuppressed = true };
            wb.Navigate(uriBuilder.Uri.ToString());
            PanelManager.DisplayControl(wb, "Bird's eye");
        }
 
        public static void DisplayStreetView(this Point point)
        {
            System.Windows.Forms.WebBrowser wb = new System.Windows.Forms.WebBrowser() { ScriptErrorsSuppressed = true };
            UriBuilder uriBuilder = new UriBuilder(new Uri("http://samples.sistemigis.it/StreetViewArcMap/panoAvailable.html"));
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("lat={0}", point.Y.ToString(Helper.CultureInfoUS));
            sb.Append('&');
            sb.AppendFormat("long={0}", point.X.ToString(Helper.CultureInfoUS));
            sb.Append('&');
            sb.AppendFormat("width={0}", 600);
            sb.Append('&');
            sb.AppendFormat("height={0}", 400);
            uriBuilder.Query = sb.ToString();
            wb.Navigate(uriBuilder.Uri.ToString());
            PanelManager.DisplayControl(wb, "Street View");
        }
 
    }
 
    /// <summary>
    /// class of helper
    /// </summary>
    public static class Helper
    {
        /// <summary>
        /// culture for lat-long
        /// </summary>
        public static readonly CultureInfo CultureInfoUS = new CultureInfo("en-US");
 
        /// <summary>
        /// culture supported from Map Control (Microsoft)
        /// </summary>
        private static readonly string[] culturesMapControl = new string[] { "nl-BE""en-CA""en-IN""en-GB""en-US""fr-CA""fr-FR""de-DE""it-IT""ja-JP""es-MX""es-ES""es-US" };
 
        /// <summary>
        /// set culture for map control (microsoft)
        /// if current culture isn't supported it's changed with default culture of map control 
        /// </summary>
        /// <param name="currentCulture">current culture</param>
        public static void GetCultureMapControl(ref string currentCulture)
        {
            int pos = Array.BinarySearch<string>(culturesMapControl, currentCulture);
            if (pos < 0)
            {
                currentCulture = CultureInfoUS.Name;
            }
        }
    }
}

Una volta eseguiti i due extension method, è possibile utilizzare i visualizer personalizzati, nel nostro caso Bird's eye e Street View.





Occorre creare un progetto di tipo Class Library ed aggiungere nei riferimenti l'exe di LinqPad evitando di fare un'inutile copia dell'exe durante la compilazione (Copy Local = false)




Per avere pronto il plugin all'uso è possibile impostare come percorso di compilazione la cartella dei plugin di LinqPad.



Per creare e/o impostare questa cartella in LinqPad selezionare la voce Preferences dal menu Edit  (tab Folders)



Tutte le dll e gli exe in questa cartella vengono automaticamente riferiti in LinqPad.

lunedì 15 giugno 2009

SQL Server 2008 - Virtual Earth

Nella versione 2008 di SQL Server sono stati introdotti due nuovi tipi di dati: Geometry e Geography.
Per capire la differenza tra i due tipi di dati potete trovare la documentazione su MSDN.

Vediamo ora come caricare uno shapefile da ArcGIS Desktop (mediante l'extension Data Interoperability) in SQL Server 2008.

Per questo esempio potete anche utilizzare la versione SQL Server 2008 Express SP1 e il tool di Morten Nielsen.

Come si può vedere dalla figura qui sotto, dagli Arctoolbox si seleziona 'Quick Export' e dalla lista dei formati si seleziona Microsoft SQL Server Spatial. Lo shapefile è stato preventivamente proiettato in wgs84.








Una volta caricati, è possibile visualizzarli in Virtual Earth. In questo momento non abbiamo un metodo diretto per poterli visualizzare poichè gli output da SQL Server 2008 sono il WKT e il GML e il formato nativo che nei client .NET si traduce nei tipi .NET SqlGeometry e SqlGeography; mentre Virtual Earth necessita di GeoRSS, KML, xml personalizzato da processare con javascript personalizzato o stringhe Javascript da passare ad eval().


In questo esempio creiamo una stored procedure (GetLimiteComunale) che chiamiamo tramite un servizio WCF utilizzando Linq to SQL. La stored procedure restituisce la versione GML (nell'esempio eliminiamo la parte di tag di apertura e chiusura) della feature richiamata. Nel servizio utilizziamo poi l'utility GeoRssUtils per pubblicare i dati su Virtual Earth.







In Visual Studio 2008 trasciniamo le stored procedure sul design della classe Linq to SQL



e questo è il metodo nel servizio WCF

public SyndicationFeedFormatter GetLimiteComunale(string id)
    {
        var geoData = new GeoRssData("GetLimiteComunale", "Seleziona comune");
        using (var db = new SpatialDataDataContext())
        {
            var result = db.GetLimiteComunale(int.Parse(id)).First();
            geoData.AddPolygon(result.Name, string.Format("Comunità Montana:{0}", result.Comunità_Montana), result.Polygon);
        }
 
        return new Rss20FeedFormatter(GeoRssFeedBuilder.GetFeed(geoData));
    }


sulla parte client richiamiamo il servizio WCF:

$(document).ready(function() {
 
    map = new VEMap("myMap");
    map.LoadMap();
    map.SetCenterAndZoom(new VELatLong(45.132, 7.438), 10);
 
    $("#btnIdGetLimiteComunale").click(function() {
        var request = "SpatialData.svc/GetLimiteComunale/" + $("#txtIdComune").val();
 
        var layer = new VEShapeLayer();
        var layerSpec = new VEShapeSourceSpecification(
                                    VEDataType.GeoRSS,
                                    request,
                                    layer);
 
        map.ImportShapeLayerData(layerSpec);
    });



Stessa cosa facciamo con la stored procedure GetLimitiComunaliLimitrofi. In questo caso viene mostrato come utilizzare le funzioni spaziali messe a disposizione da SQL Server (vedi http://msdn.microsoft.com/en-us/library/bb895266.aspx ). Nello specifico selezioniamo i comuni confinanti con il comune cercato.




Con la terza stored procedure (GetLimiteComunaleJSON) restituiamo il dato al servizio WCF in formato WKT e sul client inviamo i dati in formato GeoJSON che verranno poi processati mediante l'helper javascript per VE.


Sul client:
$("#btnIdAddPointGeoJSON").click(function() {
        var v = new VEGeoJSON(map);
        $.ajax({ type: "POST",
            url: "SpatialData2.svc/GetLimiteComunaleJSON",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: '{"id":"' + $("#txtIdComune").val() + '"}',
            success: function(data) {
 
                var geoJSON = eval('(' + data.d + ')');
                v.addGeoJSON(geoJSON);
            }
        });



Per la parte javascript ho utilizzato la libreria javascript jquery.

Scarica qui il codice della soluzione.

venerdì 5 dicembre 2008

Linq to XML

Con linq è semplice interrogare un element: in questo esempio ho copiato una parte di file GML.

XElement gml = XElement.Parse(

        @"<features><feature fid=""142"" featuretype=""school"" description=""A middle school"">

        <polygon name=""extent"" srsname=""epsg:27354"">

        <linestring name=""extent"" srsname=""epsg:27354"">

        <cdata>

        491888.999999459,5458045.99963358 491904.999999458,5458044.99963358

        491908.999999462,5458064.99963358 491924.999999461,5458064.99963358

        491925.999999462,5458079.99963359 491977.999999466,5458120.9996336

        491953.999999466,5458017.99963357 </cdata>

        </linestring>

        </polygon>

        </feature><feature fid=""143"" featuretype=""house"" description=""a house"">

        <polygon name=""extent"" srsname=""epsg:27354"">

        <linestring name=""extent"" srsname=""epsg:27354"">

        <cdata>

        491888.999999459,5458045.99963358 491904.999999458,5458044.99963358

        491908.999999462,5458064.99963358 491924.999999461,5458064.99963358

        491925.999999462,5458079.99963359 491977.999999466,5458120.9996336

        491953.999999466,5458017.99963357 </cdata>

        </linestring>

        </polygon>

        </feature></features>");

 

 

        //Seleziono la feature con fid = 143

 

        var query = from p in gml.Elements("feature") where (int)p.Attribute("fid") == 143 select p;

 

        //visualizzo i suoi attributi

        foreach (var rec in query)

            Console.WriteLine("Feature: type:{0} - description: {1}", rec.Attribute("featureType").Value, rec.Attribute("Description").Value);

mercoledì 22 ottobre 2008

Esempio Linq utilizzato con ClassBreaks




using System;

using System.Collections.Generic;

using System.Drawing;

using System.Linq;

using ESRI.ArcGIS.ADF.BaseClasses;

using ESRI.ArcGIS.Carto;

using ESRI.ArcGIS.Controls;

using ESRI.ArcGIS.Display;

using ESRI.ArcGIS.esriSystem;

using ESRI.ArcGIS.Geodatabase;

namespace Studioat.ArcEngine

{

 

  public sealed class Classify : BaseCommand

  {

 

 

    private IHookHelper m_hookHelper = null;

    private ITOCControl2 m_tocControl = null;

    public Classify(ITOCControl2 tocControl)

    {

 

      base.m_caption = "Classify LINQ";

 

      m_tocControl = tocControl; 

 

      try

      {

        string bitmapResourceName = GetType().Name + ".bmp";

        base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);

      }

      catch (Exception ex)

      {

        System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap");

      }

    }

 

    #region Overriden Class Methods

 

    /// <summary>

    /// Occurs when this command is created

    /// </summary>

    /// <param name="hook">Instance of the application</param>

    public override void OnCreate(object hook)

    {

      if (hook == null)

        return;

 

      try

      {

        m_hookHelper = new HookHelperClass();

        m_hookHelper.Hook = hook;

        if (m_hookHelper.ActiveView == null)

          m_hookHelper = null;

      }

      catch

      {

        m_hookHelper = null;

      }

 

      if (m_hookHelper == null)

        base.m_enabled = false;

      else

        base.m_enabled = true;

    }

 

    /// <summary>

    /// Occurs when this command is clicked

    /// </summary>

    public override void OnClick()

    {

      //nedd to get the layer from the custom-property of the map

      if (null == m_hookHelper)

        return;

 

      //get the mapControl hook

      object hook = null;

      if (m_hookHelper.Hook is IToolbarControl2)

      {

        hook = ((IToolbarControl2)m_hookHelper.Hook).Buddy;

      }

      else

      {

        hook = m_hookHelper.Hook;

      }

 

      //get the custom property from which is supposed to be the layer to be saved

      object customProperty = null;

      IMapControl3 mapControl = null;

      if (hook is IMapControl3)

      {

        mapControl = (IMapControl3)hook;

        customProperty = mapControl.CustomProperty;

      }

      else

        return;

 

      if ((null == customProperty) || !(customProperty is ILayer) || !(customProperty is IFeatureLayer))

        return;

 

 

      IFeatureLayer featureLayer = customProperty as IFeatureLayer;

      IGeoFeatureLayer geoFeatureLayer = featureLayer as IGeoFeatureLayer;

      IFeatureClass featureClass = geoFeatureLayer.DisplayFeatureClass;

 

      string sFieldName = "Popolazione";

      int numClasses = 5;

 

 

      IBasicHistogram basicHistogram = new BasicTableHistogram();

      ITableHistogram tableHistogram = basicHistogram as ITableHistogram;

      tableHistogram.Field = sFieldName;

      tableHistogram.Table = featureClass as ITable;

 

      object oVals =new object();

      object oFreqs =new object();

      basicHistogram.GetHistogram(out oVals, out oFreqs);

      IClassifyGEN classifyGEN = new NaturalBreaks();

 

      classifyGEN.Classify(oVals, oFreqs, ref numClasses);

 

      IClassBreaksRenderer render = new ClassBreaksRenderer();

      double[] cb = (double[])classifyGEN.ClassBreaks;

 

      double[] dVals = (double[])oVals;

      int[] iFreqs = (int[])oFreqs;

 

      var dValsL = dVals.Select((num, index) => new { Num = num, Index = index });

      var iFreqsL = iFreqs.Select((num, index) => new { Num = num, Index = index });

 

      var pairs = from a in dValsL join b in iFreqsL on a.Index equals b.Index select new { Values = a.Num, Frequency = b.Num };

 

 

      List<int> listCount = new List<int>();

 

      for (int i = 0; i < numClasses; i++)

      {

 

          var a = from p in pairs where ((i == 0) ? (p.Values >= cb[i]) : (p.Values > cb[i])) && p.Values <= cb[i + 1] select new { p.Frequency };

          int j = a.Sum(p => p.Frequency);

          listCount.Add(j);

 

      }

 

 

      render.Field = sFieldName;   

      render.BreakCount = numClasses;   

      render.MinimumBreak = cb[0];   

 

 

 

 

      IAlgorithmicColorRamp colorRamp = new AlgorithmicColorRamp();

      colorRamp.Algorithm = esriColorRampAlgorithm.esriCIELabAlgorithm;  

 

 

      IRgbColor color1 = new RgbColor();

 

      IRgbColor color2 = new RgbColor();

      color1.Red = 255 ;  

      color1.Green = 210;   

      color1.Blue = 210;   

      color2.Red = 190;   

      color2.Green = 0;   

      color2.Blue = 170;   

      colorRamp.FromColor = color1;   

      colorRamp.ToColor = color2;   

      colorRamp.Size = 5 ;

      bool ok = true;

      colorRamp.CreateRamp (out ok);

 

 

      IClassBreaksUIProperties  classBreaksUIProperties = render as IClassBreaksUIProperties;   

      classBreaksUIProperties.ColorRamp = "Custom";

      IEnumColors enumColors = colorRamp.Colors; 

      enumColors.Reset(); 

      for (int i = 0;i<numClasses;i++)

      {

        render.set_Break(i,cb[i + 1]);

 

        render.set_Label(i, string.Format("{0} - {1} - Count {2}", cb[i], cb[i + 1], listCount[i]));

        classBreaksUIProperties.set_LowBreak(i, cb[i]);       

        ISimpleFillSymbol simpleFillSymbol = new SimpleFillSymbol();       

        simpleFillSymbol.Color = enumColors.Next();       

        render.set_Symbol(i,simpleFillSymbol as ISymbol);   

      }                

 

      geoFeatureLayer.Renderer = render as IFeatureRenderer;

 

      mapControl.ActiveView.Refresh();

      m_tocControl.Update();

 

    }

 

    #endregion

  }

}



Qui puoi scaricare la soluzione in VS2008 ClassBreakLinq