LightSwitch i WCF RIA Service

U svakom razvojnom okruženju postoje određena ograničenja koja nas onemogućavaju da kreiramo određene stvari. Visual Studio LightSwitch nije izuzetak.

Naime, LightSwitch omogućava rad samo sa jednim entitetom (tabelom) u okviru jednog ekrana. Ova činjenica može biti problem, ukoliko imamo situaciju da moramo da “radimo” sa dva entiteta u isto vrijeme. Jedno od rješenja bi moglo biti kreiranje pogleda (View) nad bazom koja bi uključila dvije tabele. Kako je moguće u okviru LightSwitch-a prilikom povezivanja sa spoljnim izvorom podataka uvesti pored tabele i pogled (View) onda bi problem mogao biti riješen. Međutim, postoje dva moguća problema:

  1. Ne postoje uvijek privilegije u spoljnjem izvoru podataka (bazi podataka) za kreiranjem objekata u bazi (kreiranje pogleda-Views)
  2. Ukoliko se kreiraju entiteti u okviru lokalne baze (ApplicationData) u okviru LightSwitch-a, tada nije moguće kreirati pogled u okviru baze koju LightSwitch kreira iz izvora podataka ApplicationData

Druga moguća situacija u okviru LightSwitch-a koja bi  nam zasmetala je činjenica da LightSwitch ne omogućava kreiranje agregatnih upita nad bazom (SUM, Group By).

Oba navedena nedostatka u okviru LightSwitch se mogu prevazići korišćenjem WCF RIA Service.

Preduslovi za kreiranje WCF RIA Service u LightSwitch 2011:

  1. Visual Studio 2010 Professional ili veća verzija
  2. LightSwitch 2011 (ne LightSwitch u okviru Visual Studio 11 Beta)

Model podataka

Kao primjer korišćenja WCF RIA Service, prikazaću kreiranje servisa sa agregatnim upitom nad bazom narudžbi za kurseve (SUM i Group By) za sledeći model podataka:

TrainingCourseScheme

Cilj: kreirati upit koji će dati pregled ukupnih zarada po kursevima

Tabele se nalaze u spoljnoj SQL Server bazi TrainingCourse koja se nakon povezivanja u okviru LightSwitch aplikacije (Add Data Source/Database/TrainingCourses) pojavljuje u izvoru podataka kao TrainingCourseData:

TrainingCourseData

Kreiranje WCF RIA Service

U okviru postojećeg rješenja (Solution) MyTrainingCourseApp ću dodati novi Class Library putem komandi File –> Add –> New Project sa nazivom WCFRIA_Project:

NewClassLibrary

Kao rezultat dobijamo još  jedan projekat WCFRIA_Report u okviru istog rješenja:

WCFRIA_ReportClassLibrary

Potom je potrebno dodati u References novokreiranog projekta WCFRIA_Report:

AddReferenceClassLibrary

sledeće reference iz .NET sekcije:

  • System.ComponentModel.DataAnnotations
  • System.Configuration
  • System.Data.Entity
  • System.Runtime.Serialization
  • System.ServiceModel.DomainServices.Server (Potražite na putanji %ProgramFiles(x86)%\Microsoft SDKs\RIA Services\v1.0\Libraries\Server ukoliko se ne nalazi u .Net sekciji)
  • System.Web

Promijeniti naziv klase Class1.cs u TrainingCourseReportData.cs. Izvršite izmjene koje nudi Visual Studio (dugme Yes):

RenameClass1

Povezivanje na bazu i kreiranje upita u WCF RIA Service

Da bi imali pristup spoljnoj bazi podataka (TrainingCourse) putem WCF RIA servisa, jedan od mogućih rješenja je kreiranje ADO .NET Entity Framework modela koji bi se vezao za spoljnu bazu i koji bi čuvao šemu baze. Problem je prilikom izmjene šeme baze očuvanje izmjena u Entity Framework-u. Da bi se to izbjeglo, koristićemo Entity Framework u okviru LightSwitch aplikacije koja čuva model spoljne baze koristeći opciju Add As Link na sledeći način.

U okviru WCFRIA_Report projekta dodaćemo postojeću stavku (Add –> Existing Item):

AddExistingItem

Lociraćemo se u okviru projekta gdje je kreirana klasa za TrainingCoursesData.cs na putanji: MyTrainingCoursesApp\ServerGenerated\GeneratedArtifacts i obavezno odabrati Add As Link opciju:

AddAsLink

Na ovaj način, oba projekta (LightSwitch projekat i WCF RIA Service projekat) u okviru našeg rješenja će dijeliti informaciju o istoj bazi na jednom mjestu a vezano za TrainingCourse bazu podataka:

LinkToDataSource

Na kraju je potrebno u klasi TrainingCourseReportData.cs dodati naredni kod za:

  1. Kreiranje ObjectContext
  2. Kreiranje željenog agregatnog upita

Programski kod u okviru klase TrainingCourseReportData.cs :

using System.Linq;
using System.ServiceModel.DomainServices.Server;
using System.Web.Configuration;
using System.Data.EntityClient;
using System.ComponentModel.DataAnnotations;
using TrainingCoursesData.Implementation;

namespace WCFRIA_Report
{
  public class TrainingCourseReportData : DomainService
  {
    private TrainingCoursesDataObjectContext var_context;
    public TrainingCoursesDataObjectContext Context
    {
      get
      {
        if (this.var_context == null)
        {
          EntityConnectionStringBuilder builder = new EntityConnectionStringBuilder();
          builder.Metadata =
          "res://*/TrainingCoursesData.csdl|res://*/TrainingCoursesData.ssdl|res://*/TrainingCoursesData.msl";
          builder.Provider = "System.Data.SqlClient";
          builder.ProviderConnectionString =
          WebConfigurationManager.ConnectionStrings["TrainingCoursesData"].ConnectionString;

          this.var_context = new TrainingCoursesDataObjectContext(builder.ConnectionString);
        }
        return this.var_context;
      }
  }

    /// Override the Count method in order for paging to work correctly
    protected override int Count<T>(IQueryable<T> query)
    {
      return query.Count();
    }

    [Query(IsDefault = true)]
    public IQueryable<CourseSales> GetSalesTotalsByCourse()
    {
      return this.Context.Orders
        .GroupBy(od => od.Course)
        .Select(g =>
          new CourseSales()
          {
            CourseId = g.Key.CourseId,
            CourseName = g.Key .CourseName,
            CourseSalesTotalFloat = g.Sum(od =>
              ((float)(od.Price * od.Attendees)))
          });
    }
  }

  public class CourseSales
  {
    [Key]
    public int CourseId { get; set; }
    public string CourseName { get; set; }
    public decimal CourseSalesTotal { get; set; }

    // This is needed because the cast isn't allowed in LINQ to Entity queries
    internal float CourseSalesTotalFloat
    {
      set
      {
        this.CourseSalesTotal = new decimal(value);
      }
    }
  }

}

Napomene vezane za programski kod:

  1. TrainingCoursesDataObjectContext kreira dinamički vezu ka bazi (TrainingCoursesData) koju koristi WCF RIA servis
  2. Klasa TrainingCourseReportData mora da naslijedi DomainService klasu
  3. Metoda GetSalesTotalsByCourse grupiše narudžbe po kursevima i računa ukupnu vrijednost kursa po formuli (Price * Attendees)
  4. Klasa CourseSales je Domain Service koja definiše naš novi entitet sa poljima CourseId (atribut [Key]), CourseName i CourseSalesTotal u kojoj ćemo čuvati podatke koje nam proslijedi metoda GetSalesTotalsByCourse
  5. Ukoliko bi željeli da se povežemo na internu bazu (ApplicationData) u tom slučaju bi konekcioni string trebao da bude “_IntrinsicData” umjesto “TrainingCoursesData
  6. Metoda GetSalesTotalsByCourse sadrži atribut [Query(IsDefault = true)]. Svaki entitet u okviru domain servise klase mora da sadrži default metodu koju će LightSwitch koristiti za vraćanje kolekcije entiteta i ta metoda ne smije da sadrži parametre

Povezivanje sa WCF RIA Service u okviru LightSwitch aplikacije

Nakon kreiranja WCF RIA servisa, potrebno je u okviru LightSwitch aplikacije da se povežemo na kreirani servis putem komandi: Date Sources –> Add Data Sources –> WCF RIA Service:

WCFDataSource

Odaberemo dugme Add Reference:

AddReference

Izaberemo projekat WCFRIA_Report iz sekcije Projects:

SelectProject

Nakon izvjesnog vremena će se pojaviti izabrani projekat u listi WCF RIA servisa:

WCFAppear

Kao rezultat izbora WCF RIA servisa će se pojaviti kreirani entitet CourseSales u okviru izvora podataka sa nazivom TrainingCourseReportDataWCF:

WCFEntities

WCF RIA servis se ponaša kao bilo koji drugi izvor podataka:

WCFDataSourceFinal

Da bi provjerili da li funkcioniše naš servis, kreiraćmo Search ekran za entitet CourseSales sa nazivom SearchCourseSales:

SearchScreen

Na osnovu Search ekrana je moguće koristiti Silverlight Chart kontrolu za prikaz podataka u obliku grafikona kojim bi se vizuelno bolje predstavili podaci.

Zaključak

WCF RIA Service je mehanizam kojim se proširuje mogućnost LightSwitch aplikacija. U pokazanom primjeru se koriste podaci za pregled podataka, dok je moguće kreirati WCF RIA servis i za izmjenu podataka. Takođe je moguće koristiti ostale agregatne funkcije u okviru WCF RIA servisa.

Credits:

About Spaso Lazarevic

Spaso Lazarevic is Senior Software Developer working with Microsoft technologies. Leader of .NET User Group Bijeljina, speaker at Microsoft events, writter and blogger. Microsoft MVP for Visual C#.
This entry was posted in Programming and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s