Citat:
Mikelly: Dobri ste, citajuci vase postove naucih i ja ponesto.
Svi mi ovde ucimo...
Mikelly, ja sam predlozio malo drugaciji pristup od onog koji si ti ovde opisao. Evo agende:
1) napraviti thread safe BindingSource klasu. Neka se zove BindingSourceSync, gde "Sync" stoji za "synchronised" - u smislu sinhronizacije tredova
2) sve objekte za rad sa podacima (DataSet, BindingSource-ve, metode za rad sa DB...) staviti "pod istu kapu" - singleton klasu koju ce koristiti razlicite forme. Singleton klasu koristimo jer nam treba jedna i samo jedna instanca ove klase. Ovako razdvajamo sloj podataka od sloja prezentacije (GUI-ja). Ta klasa se moze zvati BindingSourceManager.
3) povezati kontrole sa razlicitih formi sa BindingSource-vima
4) definisati i implementirati akcije koje se izvrsavaju kada se iz GUI-ja menjaju podaci u DataSet-u
Evo i ideja za implementaciju:
1)
Citat:
Mikelly:
kako se to "zakljucavaju" podaci?
"zakljucavanje" podataka se odnosi na kontrolu pristupa podacima (memoriji sa podacima) kada joj istovremeno moze pristupati vise tredova. Poenta je da se jednom tredu onemoguci pristup podacima sve dok drugi tred ne izvrsi neku operaciju nad njima. Na internetu ima mnogo clanaka o ovom problemu a ja preporucujem ova dva:
http://www.albahari.com/threading/part2.html#_Synchronization_Essentials
http://msdn2.microsoft.com/en-us/library/yy12yx1f.aspx
U njima se moze procitati da je za pravljenje thread-safe klase neophodno imati sinhronizacioni objekat. Klasa BindingSource ima jedan clan koji se zove SyncRoot i cija namena je upravo da posluzi kao sinhronizacioni objekat. Evo kako bi otprilike trebalo da izgleda thread safe BindingSource klasa:
Code:
public class BindingSourceSync : BindingSource
{
public override void Insert(int index, object value)
{
lock (SyncRoot)
{
base.Insert(index, value);
}
}
public override void Remove(object value)
{
lock (SyncRoot)
{
base.Remove(value);
}
}
// na slican nacin ovde treba override-ovati GetEnumerator, RemoveAt, Add, Clear, Count, IndexOf, operator []
// ...
// ...
}
2) Singleton je klasa koja je tako implementirana da je moguce napraviti jednu i samo jednu njenu instancu. Tajna je u private konstruktoru, u kom se proverava da li je instanca vec napravljena. (Implementacija singlton klase je jos jedan primer upotrebe sinhronizacije tredova)
Evo kako bi mogao da izgleda BindingSourceManager:
Code:
public class BindingSourceManager
{
private static object _lockObj = new object();
private static BindingSourceManager _instance;
private BindingSourceSync _bindingSource;
public BindingSourceSync GetBindingSource
{
get
{
return _bindingSource;
}
set
{
_bindingSource = value;
}
}
// ovo je data source (to moze biti i DataSet...bilo sta sto se kaci na bazu i popunjava podacima iz nje)
private DataTable _dataTable;
private BindingSourceManager()
{
// kreirati _dataTable
// (...)
// ovde (ili, jos bolje, u nekoj posebnoj metodi) popuniti _dataTable
// (...)
_bindingSource = new BindingSourceSync();
_bindingSource.DataSource = _dataTable;
}
// singleton pattern
public static BindingSourceManager GetInstance
{
get
{
lock (_lockObj)
{
if (_instance == null)
{
_instance = new BindingSourceManager();
}
return _instance;
}
}
}
}
}
3) Sada ces u bilo kojoj formi u tvom projektu moci pristupati _bindingSource-u pozivom:
Code:
BindingSourceManager.GetInstance.GetBindingSource
Na primer:
Code:
this.dataGridView1.DataSource = BindingSourceManager.GetInstance.GetBindingSource;
4)
Citat:
Mikelly: Svi bindingsourceovi su na pocetnoj formi.
Imam formu na kojoj pravim racune, a na racunima se nalaze artikli. Artikli su u zasebnoj tabeli, tako da imaju svoj bindingsource. U tabeli detalja racuna nalazi se strani kljuc iz tabele artikli.
Ako sad pravim neki racun, i tamo dodajem artikle, a onda bez zatvaranja te forme otvorim formu dje radim sa artiklima, i obrisem neki od njih koji se upravo nalazi na datom racunu, kako se to manifestuje?
Ako u formi sa racunom za prikaz atributa artikala koristis drugaciji BindingSource od onog koji koristis u formi gde radis sa artiklima, nece doci ni do kakve promene jer razliciti BindingSource-vi barataju sa razlicitim kopijama podataka iz baze. Ako imamo liniju GUI kontrola - BindingSource - DataSet - DB, i ako iz kontrole nesto menjas/dodajes/brises u jednoj tabeli a sto moze uticati na stanje u nekoj drugoj tabeli, mozes ili proci kroz citav lanac i upisati novo stanje u DB, pa ici nazad i osveziti stanje u svim kontrolama, a mozes ici i samo do DataSet-a, pa tek kada se uveris da imas poravnate podatke, da ih upises u bazu.