piątek, 5 października 2012

Biblioteka Vici CoolStorage dla .NET

Dzisiaj postanowiłam bliżej przedstawić bibliotekę ułatwiającą korzystanie z bazy danych, którą wykorzystuję od początku mojej pracy w .NET.
Vici CoolStorage jest biblioteką dla .NET pozwalającą mapować obiekty relacyjnej bazy danych. Biblioteka ta jest bardzo łatwa w użyciu. Wspiera takie bazy danych jak: SQL ServerMySQLSQLiteMS Access i VistaDB.

Bibliotekę Vici CoolStorage można pobrać z tej strony: http://viciproject.com/wiki/Projects/CoolStorage/Download
Na tej stronie również znajdziemy dokumentację z opisem, jak skonfigurować połączenie z bazą danych oraz jak korzystać z samej biblioteki: http://viciproject.com/wiki/Projects/CoolStorage/Doc/UserGuide

Po pobraniu biblioteki w zależności czy jest to kod źródłowy czy skompilowana biblioteką, dołączamy ją odpowiednio do naszego projektu w Visual Studio (albo przez dodanie do solucji projektu biblioteki, albo poprzez dołączenie referencji do pliku .dll).

Następnym krokiem jest dodanie kilku linijek w pliku web.config :
1. W configuration >> configSections dodajemy definicję nowej sekcji:
<section name="CoolStorage" type="System.Configuration.NameValueSectionHandler"/>
2. Potem w configuration dodajemy sekcję CoolStorage, w której umieszamy connection string do naszej bazy danych, w moim przypadku wygląda to tak:
<CoolStorage>
    <add key="Connection.zawodycon" value="CSDataProviderMySql, Vici.CoolStorage / Server=127.0.0.1;Port=3306;Database=zawody;UID=root;PWD=mojehaslo;Allow Zero DateTime=true;default command timeout=500;Connection Timeout=500;"/>
  </CoolStorage>
Po skonfigurowaniu połączenia można przejść do korzystania z biblioteki.
Do klasy w naszym modelu danych trzeba dołączyć dwie biblioteki:
using Vici.CoolStorage;
using System.ComponentModel;
Każda tabela w bazie danych może być zmapowana na dokładnie jedną klasę. Do klasy należy dołączyć atrybut MapTo, w moim przypadku wygląda on tak:
[MapTo("zawody", "zawodycon")]
, gdzie "zawody" to nazwa mojej tabeli, na którą mapowana będzie klasa, natomiast "zawodycon" to nazwa połączenie z bazą danych, które wcześniej ustawiłam w web.configu (<add key="Connection.zawodycon" ... ).

Cała moja klasa wygląda tak:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Vici.CoolStorage;
using System.ComponentModel;

namespace Dane

{
    [DataObject]
    [MapTo("zawody", "zawodycon")]
    public abstract partial class Zawody : CSObject<Zawody, int>
    {
        public abstract int id { get; }
        public abstract string nazwa { get; set; }
        public abstract string opis { get; set; }
        public abstract DateTime data { get; set; }

/* Określenie relacji tabeli zawodów z tabelą zawodników

  Pozwoli to na odwoływanie się poprzez obiekt klasy Zawody,
  do listy zawodników przypisanych do tych zawodów */
        [OneToMany(LocalKey = "id", ForeignKey = "id_zawody")]
        public abstract CSList<Zawodnicy> Zawodnicy { get; }

/* Metoda pobierająca zawody o podanym ID */

        public static Zawody PobierzZawody(int id)
        {
            return Zawody.ReadSafe(id);
        }

/* Metoda pobierająca listę wszystkich zawodów */

        public static List<Data.Zawody> PobierzWszystkieZawody()
        {
            return Zawody.List().ToList();
        }

/* Metoda sprawdzająca czy takie same zawody nie zostały już przypadkiem dodane */

        public static bool CzyJuzDodano(string nazwa, DateTime data)
        {
            return Zawody.ReadFirst("nazwa = @nazwa AND data = @data", "@nazwa", nazwa, "@data", data) != null;
        }

/* Metoda dodająca nowe zawody */

        public static bool DodajZawody(string nazwa, string opis, DateTime data)
        {
            Zawody z = Zawody.New();
            z.nazwa = nazwa;
            z.opis = opis;
            z.data = data;
            return z.Save();
        }

            /* ciąg dalszy klasy ...*/


    }

}

Istnieje również możliwość pobrania danych z bazy bezpośrednio poprzez zapytanie sql. Jednak nie można rzutować wyniku zwróconego przez zapytanie na klasę abstrakcyjną, tak więc nasza klasa powinna wyglądać tak:
public class Zawody
{
        public int ID { get; set; }
        public string Nazwa { get; set; }
        public string Opis { get; set; }
        public DateTime Data { get; set; }
}
i wtedy możemy już wykonać zapytanie np. poprzez użycie metody RunQuery, która zwróci nam listę wyników. Parametr wstawiamy w zapytaniu jako nazwę z "@", i potem podmieniamy w metodzie wstawiając po przecinku nazwę paramteru i wartość.
var sql = "select id as ID, nazwa as Nazwa, data as Data from zawody z where z.data > @data";
var zawody = CSDatabase.Context["zawody"].RunQuery<Zawody>(sql, "@data", DateTime.Now.AddDays(-7)).ToList();
Dodatkowo zamiast RunQuery mamy do wyboru użycie metod RunSingleQuery (zwraca pojedynczy wynik), GetScalar (zwróci nam wybraną wartość) itd.
Jako przykład użycia GetScalar można podać zwrócenie ilości wyników
string sql = "select count(id) from zawody z where z.data > @data";
int ilosc = CSDatabase.Context["zawody"].GetScalar<int>(sql, "@data", DateTime.Now.AddDays(-7));
Szczegóły odnośnie użycia tych metod jak i wykorzystania metod odczytu i zapisu można znaleźć w dokumentacji :)

środa, 3 października 2012

Testujemy nasz serwis w wersji mobilnej

Z uwagi na to, że ostatnio pisaliśmy i wdrażaliśmy wersję mobilną naszego serwisu, potrzebne były narzędzie do testowania jak się sprawdza on na wersjach mobilnych. Chciałam wymienić w związku z tym kilka fajnych emulatorów do testowania: