Skip to main content

Posts

Showing posts from February, 2011

Cum se face paginare pe tabelele din Windows Azure

Daca lucram cu tabelele din Windows Azure o sa avem nevoie sa facem paginare. Default nu avem nici un mecanism de paginare, dar acesta este usor de implementat.
In postul anterior am descris modul prin care se pot obtine mai mult de 1000 de entitati dintr-un tabel. Pe baza mecanismului prezentat anterior putem sa parcurgem datele din tabel in format paginat.
Trebuie sa ne folosim de metoda Take din LINQ, care din fericire este suportata si de LINQ folosit pentru tabelele din Windows Azure( nu trebuie sa uitam ca doar o parte din LINQ este implementat pentru Windows Azure in acest moment). Apeland metoda Take putem sa obtinem doar o parte din entitati care ne sunt returnate de catre query.
Folosindu-ne de token-urile nextPartitionToken si nextRowToken putem sa luam urmatoarele x elemente incepand de pe o anumita pozitie.
Mai jos gasiti o implementare minimala a unui mecanism de paginare.
public class Pagination<TItem>
where TItem : class
{
private const string NoV…

Convert a collection of items to a string

Sunt cazuri cand avem liste pe care dorim sa le convertim intr-un string folosind un anumit delimitator.
List<string> lista=new List<string>(){ "A" , "B" , "C" };
//Output: A, B, C,
LINQ nu contine o solutie directa, putem incerca sa interam cu un foreach toate elementele din lista si sa le adaugam la un StringBuilder
StringBuilder sb=new StringBuilder();
string format = "{0}, ";
lista.ForEach(item => sb.AppendFormat(format, item));
Dar din pacate codul scris mai sus este echivalent cu un foreach clasic, doar ca iteram folosind LINQ. O solutie este sa folosim metoda String.Join, care primeste doi parametrii:
-delimitatorul;
-un array care contine lista de string-uri;
Aceasta metoda functioneaza fara probleme, singura problema care o are este ca nu functioneaza pe obiecte generice de tip IEnumerable. Pentru a rezolva acest neajuns este sa apelam la extension method si sa ne scriem propria noastra metoda pentru IEnumerable.
/// <summary>…

Cum sa obtii mai mult de 1000 de entitati dintr-un query pe tabelele din Windows Azure

Pentru a putea obtine date din tabelele din Windows Azure putem sa folosim DataServiceQuery. Acesta suporta LINQ, astfel ne va fi foarte usor sa filtram continutul.
DataServiceQuery<Person> queryPersons =
ApplicationServiceContext
.PersonEntryTable
.Where( p => p.Age >= 18 );
var result = queryPersons.Execute();
In variabila result o sa avem toate persoanele care au varsta mai mare sau egala cu 18.
Problema apare cand rezultatul contine mai mult de 1000 de entitati. Un query pe tabele din cloud va returna maxim 1000 de rezultate. In cazul in care acest numar este depasit acesta va contine doua token-uri pe baza carora se pot obtine si celelate entitati din query.
Cele doua token-uri reprezinta token-ul pentru Partition Key si Row Key. Se pot obtine din heather-ul rezultatului:
var resultQOR = (QueryOperationResponse)result;
string nextPartitionToken = null;
string nextRowToken = null;
resultQOR.Headers.TryGetValue("x-ms-continuation-NextPartitionKey", out next…

Tool-uri pentru Windows Azure

Total Cost Calculator
http://www.microsoft.com/windowsazure/economics/
O aplicatie oferita de catre Microsoft pentru a ne ajuta sa estimam preturiile unei aplicatii in loud. Estimariile nu sunt foarte exacte, dar ne pot oferii o idee asupra preturiilor in prima faza. As fi vrut sa fie mai exacta si sa ne permita sa introduce in calculul final mai multe variabile, dar in versiunea actuala trebuie sa ne multumim doar cu atat.
Nota 8.

Azure Storage Explorer
http://azurestorageexplorer.codeplex.com/
O alta aplicatie foarte utila poate sa fie Azure Storage Explorer. Prin intermediul ei putem sa interogam si sa executam operatii CRUD pe table, blob si queues aflate in cloud sau de pe masina de test. Poate sa ne fie de foarte ajutor, mai ales in faza de debug sau de testare.
Nota 10.

Windows Azure Service Management CmdLets
http://archive.msdn.microsoft.com/azurecmdlets
Ne permite sa facem deploy si sa controlam o aplicatie din cloud din linia de comanda. Putem sa scriem scripturi pe care apoi sa le r…

VM role - o noua dimensiune pentru Windows Azure

Windows Azure permite pana in acest moment doua tipuri de instance:
web role - similar cu 'Web Application', in principiu orice ce merge pe http si https;
worker role - similar cu un 'Windows Service', ruleaza neincetat prelucrand date;Nu vreau sa intru in amanunte pe aceasta tema. Pe langa aceste doua, Microsoft ne pregateste un nou rol, denumit VM role. In momentul de fata este in ultima faza de testare, urmand sa apara pe piata cat de curand.
VM role-ul o sa ne permita sa controlam in intregime masina. Este nevoie sa cream local local un VM role pe care apoi sa il copiem in cloud. Pe el o sa putem pune de exemplu Windows Server 2003, putem sa controlam tot ce este instalat pe el. Singurul dezavantaj este partea de administrate care o sa fie facuta in totalitate de utilizator. O parte din pachete de update de exemplu nu o sa mai fie facute automat sau configurarea nivelului de securitate. Iar cloud-ul NU ne ofera back-up la aceasta instanta in mod automat. In cazul in …

Code Contracts

Este un tool pentru definirea specificatiilor si pentru validarea acestora in cod.
Are la baza conceptul definit de Vienna Development Method( VDM) care defineste o metoda formala pentru definirea specificatiilor unui soft si definirea integritatii acestuia.
VDM defineste trei elemente:
invariantii - un set de conditii ce trebuie sa fie adevarate in orice moment pe durata de viata a instantei;preconditii - un grup de conditii folosite pentru validarea datelor de intrare;postconditii - una sau mai multe conditii care valideaza rezultatul;Code Contracts nu ne asigura ca programul este corect, doar ne asigura ca un set de reguli sunt indeplinite( iar o parte din specificatii sunt respectate).
La baza Code Contracts sta Spec# care apare in 2007.Aceasta librarie este integrata cu Visual Studio 2010 in 2009. Echivalentrul in Java este Eiffel, care apare cu mult inainte de Spec#.
Mai jos o sa dau un exemplu de cod scris fara Code Contracts care concateneaza o lista de cuvinte:
public string Stick(…

Intalnire RONUA: 2 martie 2011

Comunitatea RONUA din Cluj-Napoca a ajuns la a doua intalnire in acest format. Cei care doresc sa participle ii rog sa imi dea un reply la acest email pentru a putea sa stim la cate personae sa ne asteptam. Va asteptam.
Oricine e interesat in a afla si discuta subiecte interesante din lumea .NET si nu numai, e asteptat in data de 02 martie (miercuri), de la orele 19:00, la urmatoarea intalnire RONUA Cluj.

In urma votului, au ramas doua subiecte:
• ESB (enterprise service buss) - un mecanism prin care mai multe module (aplicatii) pot comunica intre ele, trimitand un fel de notificari http://en.wikipedia.org/wiki/Enterprise_service_bus (Radu Vunvulea)
• Customizable (desktop) applications design (Dragoș Andronic)
* se da un produs (desktop, windows, .net)
* 80% din functionalitate este ok pentru toti clientii insa fiecare client vrea altceva de la restul de 20% (adica doreste ca aplicatia sa ii fie customizata conform propriilor nevoi)
* ca sa realizam asta va voi prezenta 2 idei…

SOLID - Design patterns

SOLID este un acronim de la:
SRP - The Single Responsibility Principle: o clasa ar trebui sa aibe o singura responsabilitate;
OCP - The Open Closed Principle: o clasa trebuie sa fie deschisa la extindere fara a necesita modificarea ei;
LSP - The Liskov Substitution Principle: clasele derivate pot sa fi inlocuite de clasele de baza;
ISP - The Interface Segregation Principle: interfete cu granulatie fina, specifice unei anumite responsabilitati, specifice unui anumit client;
DIP - The Dependency Inversion Principle: dependintele trebuie sa fie definite prin interfete si clase abstracte si nu prin clase concrete;

The Single Responsibility Principle( SRP)
"There should never be more than one reason for a class to change." — Robert Martin
O clasa trebuie sa faca doar in singur lucru si nimic mai mult. Fiecare clasa in parte trebuie sa aiba o singura responsabilitate. O clasa care are o singura responsabilitate este mai usor de modificat, mult mai usor de inteles si mai usor de testat. To…

Metoda marcata cu abstract si override

O metoda sau o propietate poate sa fie marcata ca abstracta cand aceasta nu contine si implementarea.
O metoda sau o propietate poate sa fie marcata ca override cand vrem sa modificam implementarea si sa oferim o noua implementare pentru un menbru mostenit din clasa de baza.
Pana aici nimic deosebit, OOP pur. Oare putem sa avem o metoda care sa fie marcata atat abstracta cat si override? Raspunsul este DA. Desi pare ciudat, putem sa marcam o metoda cu aceste doua atribute:
public void abstract override DoWork();
Cand putem sa avem acest caz?
Cand avem o clasa abstracta care contine o metoda virtuala.
public abstract Actiune
{
public virtual void DoWork()
{
Console.Write("Actiune1.DoWork");
}
}
Aceasta clasa poate sa fie mostenita de o alta clasa care sa ofere o alta implementare de baza la metoda DoWork.
public abstract Actiune2 : Actiune
{
public abstract override void DoWork();
}
Orice clasa ce va implementa clasa abstracta Actiune2 o sa fie obligata sa ofere o implemen…

IComparer generic - propietatea Default

De obicei cand dorim sa putem compara doua obiecte de acelasi tip folosim IComparar. Aceasta ne pune la dispozitie metoda
int Compare(T x, T y);
Valorea returnata de aceasta metoda poate sa fie:
>0 - daca x este mai mare ca y;=0 - daca x este egal cu y;<0 - daca x este mai mic ca y; In cazul in care una( sau amandoua) din valori, metoda poate sa returneze:
>0 - daca y este null;=0 - daca x so y sunt null;<0 - daca x este mai mic ca y; Dar pentru a putea face aceasta comparatie una din valori trebuie sa fie diferita de null, atlfel o sa avem parte de NullReferenceException. Pentru a putea rezolva aceasta problema putem sa avem ceva de genul:
var valoare = x == null ? ( y == null ? 0 : -1 ) : x.CompareTo(y);
Este necesar sa verificam daca una din valor este null. Valoarea lui y nu trebe sa o verificam obligatoriu, dar cea a lui x trebuie sa o verificam mereu.
Pentru a rezolva acest neajuns, avem la dispozitie propietatea Default pe IComparable. Aceasta va crea automat comparatorul …

AutoMapper - object to object mapper

Acest mic framework ne ajuta cand trebuie sa mapam doua entita cu aceleasi propietati. In mod traditional pentru a face acest lucru trebuie sa scriem ceva de genul:
CarDb carDb = LoadFromDb(id);
// ...
Car car = new Car()
{
Type = carDb.Type,
Number = carDb.Number,
Owner = varDb.Owner,
RegFrom = carDb.RegFrom
};
Acest caz apare mai ales cand avem o aplicatie pe mai multe nivele, iar modelul care persista in baza de baza de date si modelul care ajunge la client sunt diferite.
Ce poate sa faca AutoMapper, este sa faca automat copierea valorilor proprietarilor, fara sa mai scrim noi cod. In cazul in care propietatea primeste o alta valorea sau are un nume diferit, putem sa scriem o expresie lambda care sa faca conversia.
Mai jos o sa gasiti cateva exenple:
1. Mapare intre doua entitati Car si CarDb
// Creare mapare.
Mapper.CreateMap<CarDb,Car>() ;
// Conversia propriu-zisa.
Car car = Mapper.Map<CarDb,Car>(carDb) ;
In…

HTML: Cum sa facem disable un element din drop down.

Uneori avem nevoie pe UI sa facem un element dintr-un drop-down disable. Utilizatorul sa il poata vedea, dar sa nu il poata selecta. Aceasta varianta este foarte utila cand un update la o aplicatie deja existenta, unele optiuni dispar. Pana cand toti utilizatori o sa isi faca update la configuratie( backward compatibility).
Pe fiecare optine dintr-un select avem atributul disable ce care il putem seta. Pana aici totul pare in regula:
<select name="telefon"> <option value="1">Nokia</option> <option value="2" disabled="disabled">LG</option> <option value="3">Samsung</option></select>
Optiunea de LG nu o sa poata fi selectata, dar utilizatorul o poate vizualiza, iar din codul de java script se poate selecta aceasta valoare.
Ar aparea ceva de genul acesta:
NokiaLGSamsung
Singura problema este cu IE. Acesta nu suporta acest atribut. Pentru a rezolva acest neajuns putem sa folosim urmator…

Propietati de tip array in tabelele din Windows Azure (part 2)

Partea 1 http://vunvulearadu.blogspot.com/2011/02/propietati-de-tip-vector-in-tabele-din.html
Continuare:
In ultimul meu post am descris trei variante prin care se poate persista o entitate care contine o propietate de tip array( lista) intr-un tabel. Ultima varianta, care la prima vedere pare cea mai buna era folosind DataServiceContext.
Aceasta solutie este viabila, atata timp cat nu trebe sa facem un query direct pe tabel. In acest moment tabelel din Windows Azure nu suporta pe query expresii de genu:
ContainsCountSelectDin aceasta cauza, daca avem o propietate de tip lista nu o sa putem avea un query de genul:
(item => item.ListaElemente.Contains(id)
Din aceasta cauza, pentru a putea face un astfel de query ar fi nevoie sa incarcam toate elementele din tabel si sa le procesam din cod, cea ce nu tocmai optim.
Dar nici prima varianta nu se poate folosii din pacate( lista sa fie stocata ca si un string cu un caracter despartitor), din cauza ca urmatorul query nu este suportat:
(item =>…

Propietati de tip array in tabelele din Windows Azure( part 1)

Am inceput sa folosesc din plin tabelele din Windows Azure. Orice fel de date se pot salva acolo, atata timp cat sunt serializabile.
Cu ajutorul lor am facut maparea unor entitati fara probleme. Am ajuns in momentul in care intre doua entitati A si B aveam o relatie n la m, iar intre alte doua entitati 1 la n. Fara nici o problema am scris:
public List<Guid> ItemIds { get; set; }
Am continuat sa scriu codul in continuare fara nici o problema, iar intr-un final am ajuns la unit-teste unde am avut o surpriza nu tocmai placuta. Cea ce am ignorat de la bun inceput a fost faptul ca tabele din Windows Azure nu sunt O/R, ele nu stiu sa stocheze in mod default o lista.
Greseala mea, fapta fiind deja comisa a trebuit sa caut solutii la aceasta problema. Am gasit urmatoarele solutii:
o propietate de tip string care sa stocheze id-urile despartite printr-un caracter special. Solutia destul de viabila, daca tinem cont de faptul ca obiectele care se stocheaza pe tabele nu ajung sa fie folosite pe…

Cum sa "NU" rulezi mai mult de un serviciu windows din acelasi process.

Daca vrem sa pornim mai mult de un serviciu in acelasi proces avem nevoie sa apelam urmatorul cod:
services = new ServiceBase[]
{
new DeleteService(),
new CopyService(),
new LoadService(),
};
ServiceBase.Run(services );
Dupa ce o sa executam acest cod o sa avem surpiza sa observam ca doar primul serviciu din lista a ponit. In prima faza ne gandim ca avem acelasi nume, asa ca verificam la cele trei servicii numele. Totul pare in ordine.
Urmatorul pas este sa setam serviciul pe "Share" type. Pentru acest lucru trebuie facut:
sc config "NumeServiciu" type=share
Dar din pacate problema se manifesta in continuare. Doar primul serviciu din lista de servicii porneste.

Am renuntat la acesta idee si am facut cate in install pentru fiecare servciu i…

System.Web.Helpers.Json.Decode + dynamic = generic deserialization

Azi am făcut o mare descoperire. Prin helpe-ul de web am gasit metoda Json.Decode. Se poate folosii oriunde nu doar in aplicațiile web. Este nevoie doar sa referim System.Web.Helpers.
Cu ce ne ajuta, putem face decode la orice obiect serializat prin Json, iar in combinatie cu dynamic type obtinem urmatorul cod:
var webClient = new WebClient();
var jsonResult = webClient.DownloadString("URL");
var result = Json.Decode(jsonResult);
//result.response.sets.items - depinde de cea ce returneaza Json
var listItem = new List<dynamic>(result.response.sets.items);
In listItem avem deja o lista de obiecte de orice tip deserializate. Singurul lucru in minus este ca propietatiile care se acceseaza dintr-un obiect de tip dynamic nu sunt strong type. Doar la runtime o sa stim daca proprietatea exista sau nu - din cauza la DLR( Dynamic Language Runtime).

Operatii CRUD pe tables in Windows Azure

Se da obiectul de tip Point, cu doua propietati de tip int X si Y si un id tot de tip int, unde point implementeaza TableServiceEntity.

Initalizare:
//Initializare cont (se poate incarca din fisierul de configurare).
StorageAccountInfo account = ...
TableStorage tableStorage = TableStorage.Create(account);
//Creare tabel cu un anumit nume.
tableStorage.TryCreateTable("Point");
Salvare:
Point point = new Point();
...
TableStorageDataServiceContext context = table.GetDataServiceContext();
context.AddObject(point);
//Doar pe save se salveaza in tabel obiectul nostru.
context.Save();
Interogare:
TableStorageDataServiceContext context = table.GetDataServiceContext();
//Trebuie specificat numele tabelului. Un tabel poate sa contina orice tip de obiecte, chiar si de tipuri diferite.
var query = context .CreateQuery("Point").Where(item => item.Id == 10);
IEnumerable resultList = new TableStorageDataServiceQuery((DataServiceQuery)query).ExecuteAll();
Stergere:
//Dupa ce prin avem obiectul d…

Windows Azure - static properties & fields

Variabilele de tip static pe Azure nu sunt chiar statice. Din cauza ca nu stim intr-un anumit moment pe ce instanta putem sa ajunge printr-un call, nu trebuie sa presupunem ca intre doua call-uri consecutive o sa ajungem pe aceiasi masina.
Aceasta problema apare mai ales in cazul variabilelor care le initializam printr-o metoda publica intr-un anumit moment diferit de initializarea aplicatiei.
Din aceasta cauza cel mai bine este sa lucram cu propietati, nu cu field-uri si sa avem un cod asemanator cu cel pentru Singleton.
private static ObjA _item;
private static object _itemLock;
public static ObjA Item
{
get;
{
if(_item == null)
{
InitItem ();
}
return _item;
}
}

private static InitItem()
{
lock(_itemLock)
{
if(_item == null)
{
_item = Init…

ConvertAll - Conversia unei liste mult mai usor

Avem urmatorul scenariu. O lista de elemente de tip A, pe care trebuie sa o convertim la o lista de tip B. Pentru a putea rezolva aceasta problema putem să implementam operatorul implicit sau explicit de conversie, iar apoi să iteram prin lista pentru a face conversia la tipul B.
List<A> listaA;
List<B> listaB;
...
foreach(A a in listaA)
{
listaB.Add(a);
}

sau
listaB.foreach(item=>listaB.Add(item));
Ambele soluții sunt rezonabile, dar e puțin mai greu de înțeles ca in spate se face o conversie. Pentru a face codul mai clar putem să facem in felul următor:
listaB = listaA.ConvertAll<B>(item => item)
Ce am scris mai sus? Fiecare element din listaA convertestel in tipul B si adaug-al in colecția care rezulta. item => item am putut sa scrie deoarece am presupus ca un operator de conversie implicita sau explicita intre cele doua tipuri a fost deja implementat.
In cazul in care acesta nu ar fi implementat am avea ceva asemanator:
Din
private B ConvertAToB(A a) { return new B…

Cum sa verificam daca un path este valid

Uneori avem nevoie să verificam dacă un path dat de utilizator este valid. Asa cum exista System.IO.File.Exist() exista pentru a face aceasta verificare si System.IO.Directory.Exist().
Iata mai jos si un exemplu:
string path = "d:/locatie";
if(System.IO.Directory.Exist(path))
{
//path-ul este valid.
} else
{
// path-ul nu este valid.
}
In cazul in care path-ul contine si numele unui fisier putem sa facem urmatorul artificiu:
string path = "d:/locatie/a.txt";
if(System.IO.Directory.Exist(GetDirectoryName(path)))
{
//path-ul este valid.
} else
{
// path-ul nu este valid.
}

Cand sa folosim System.Thread.Timer

In .NET putem sa alegem din 3 tipuri de timer:
System.Timer - thread timer;System.Thread.Timer - server base timer;System.Windows.Forms.Timer - windows base timer;System.Windows.Forms.Timer se foloseste in general pe UI, cand trebuie sa facem update. System.Timer o sa il folosim de obicei de obicei pe partea de server cand vrem mai multe flexibilitate si mai mult optiuni. Din cele trei timer-uri, acesta are cele mai multe optiuni.
System.Thread.Timer, care rulează un nou thread pentru operațiile sale. Acesta este folositor când vrem sa facem operații asyncron.
System.Threading.Timer timer = new System.Threading.Timer(new TimerCallback(ExecutaCeva), null, 0, 2000);
...
private void ExecutaCeva(object obj)
{
....
}
Pentru a face disable/enable putem sa folosim:
timer.Change(Timeout.Infinite, Timeout.Infinite); //Disable.
timer.Change(0, 2000); //Enable.
Cea ce mi s-a parut foarte folositor la acest imer sunt parametrii lui Change si ultimii doi parametrii a contructorului. Prin intermediul lor pu…

Cum sa salvezi un stream direct intr-un fisier

Cred ca este a 2-a oara când întâlnesc aceasta cerința in decurs de câteva săptămâni.
Se da un stream și o locație unde trebuie salvat, se cere să se salveze conținutul la stream in locația data. Din păcate API-ul de .NET nu ne permite să facem acest lucru doar dintr-un apel.
O soluție propusa este următoarea:
/// <summary>
/// Save the stream to the given location.
/// </summary>
/// <param name="stream">The stream.</param>
/// <param name="filePath">The file path where is saved.</param>
/// <param name="blockSize">The size of the buffer(in kB)</param>
public static void SaveStream(this Stream stream,String filePath,SeekOrigin seekOrigin=SeekOrigin.Begin,int blockSize=1)
{
//Set the poinder to the begin of the stream.
if(stream.CanSeek && seekOrigin==SeekOrigin.Begin)
{
stream.Seek(0, SeekOrigin.Begin);