Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.DataAccess.ADOHelper/DataAdapterBase.cs @ 1492

Last change on this file since 1492 was 1492, checked in by svonolfe, 15 years ago

Removed connection property from session (#527)

File size: 7.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Data;
24using System.Collections.Generic;
25using System.Text;
26using System.Linq;
27using System.Threading;
28using HeuristicLab.DataAccess.Interfaces;
29
30namespace HeuristicLab.DataAccess.ADOHelper {
31  public abstract class DataAdapterBase<AdapterT, ObjT, RowT>
32    where AdapterT : new()
33    where RowT : System.Data.DataRow
34    where ObjT : IPersistableObject, new() {
35
36    private ISession session;
37
38    private IDataAdapterWrapper<AdapterT, ObjT, RowT> dataAdapter;
39
40    private static Mutex lockersMutex =
41      new Mutex();
42
43    private static IDictionary<object, Mutex> lockers =
44      new Dictionary<object, Mutex>();
45
46    private static IDictionary<object, int> lockCount =
47      new Dictionary<object, int>();
48
49    protected DataAdapterBase(
50      IDataAdapterWrapper<AdapterT, ObjT, RowT> dataAdapter) {
51      this.dataAdapter = dataAdapter;
52    }
53
54    protected void LockRow(object id) {
55      Mutex rowLock = null;
56
57      /////begin critical section////
58      lockersMutex.WaitOne();
59
60      if (!lockers.ContainsKey(id)) {
61        lockers[id] = new Mutex();
62        lockCount[id] = 0;
63      }
64      rowLock = lockers[id];
65      lockCount[id]++;
66     
67      lockersMutex.ReleaseMutex();
68      /////end critical section////
69
70      rowLock.WaitOne();
71    }
72
73    protected void UnlockRow(object id) {
74      Mutex rowLock = lockers[id];
75      rowLock.ReleaseMutex();
76
77      /////begin critical section////
78      lockersMutex.WaitOne();
79
80      lockCount[id]--;
81      if (lockCount[id] == 0)
82        lockers.Remove(id);
83
84      lockersMutex.ReleaseMutex();
85      /////end critical section////
86    }
87   
88    protected AdapterT Adapter {
89      get {
90        return dataAdapter.TransactionalAdapter;
91      }
92    }
93
94    public ISession Session {
95      get {
96        return this.session;
97      }
98
99      set {
100        if (!(value is Session))
101          throw new Exception("Can only bind to ADO session");
102
103        this.session = value;
104        this.dataAdapter.Session = value as Session;
105      }
106    }
107
108    public object InnerAdapter {
109      get {
110        return this.Adapter;
111      }
112    }
113
114    #region Abstract methods
115    protected abstract RowT ConvertObj(ObjT obj, RowT row);
116
117    protected abstract ObjT ConvertRow(RowT row, ObjT obj);
118    #endregion
119
120    protected delegate IEnumerable<RowT> Selector();
121
122    protected ObjT Convert(RowT row, ObjT obj) {
123      try {
124        obj = ConvertRow(row, obj);
125        return obj;
126      }
127      catch (DeletedRowInaccessibleException) {
128        return default(ObjT);
129      }
130      catch (RowNotInTableException) {
131        return default(ObjT);
132      }
133    }
134
135    protected RowT FindSingleRow(Selector selector) {
136      RowT row = default(RowT);
137
138      IEnumerable<RowT> found =
139        selector();
140
141      if (found.Count<RowT>() == 1)
142        row = found.First<RowT>();
143
144      return row;
145    }
146
147    protected ObjT FindSingle(Selector selector) {
148      ITransaction trans =
149       session.GetCurrentTransaction();
150      bool transactionExists = trans != null;
151      if (!transactionExists) {
152        trans = session.BeginTransaction();
153      }
154
155      try {
156        RowT row = FindSingleRow(selector);
157
158        ObjT result;
159        if (row != null) {
160          ObjT obj = new ObjT();
161          obj = Convert(row, obj);
162
163          result = obj;
164        } else {
165          result = default(ObjT);
166        }
167
168        return result;
169      }
170      finally {
171        if (!transactionExists && trans != null) {
172          trans.Commit();
173        }
174      }
175    }
176
177    protected ICollection<ObjT> FindMultiple(Selector selector) {
178      ITransaction trans =
179       session.GetCurrentTransaction();
180      bool transactionExists = trans != null;
181      if (!transactionExists) {
182        trans = session.BeginTransaction();
183      }
184
185      try {
186        IEnumerable<RowT> found =
187          selector();
188
189        IList<ObjT> result =
190          new List<ObjT>();
191
192        foreach (RowT row in found) {
193          ObjT obj = new ObjT();
194          obj = Convert(row, obj);
195          if (obj != null)
196            result.Add(obj);
197        }
198
199        return result;
200      }
201      finally {
202        if (!transactionExists && trans != null) {
203          trans.Commit();
204        }
205      }     
206    }
207
208    protected virtual RowT GetRowById(Guid id) {
209      return FindSingleRow(
210        delegate() {
211          return dataAdapter.FindById(id);
212        });
213    }
214
215    protected virtual void doUpdate(ObjT obj) {
216      if (obj != null) {
217        RowT row = null;
218        Guid locked = Guid.Empty;
219
220        if (obj.Id != Guid.Empty) {
221          LockRow(obj.Id);
222          locked = obj.Id;
223
224          row = GetRowById(obj.Id);
225        } else {
226          obj.Id = Guid.NewGuid();
227        }
228
229        if (row == null) {
230          row = dataAdapter.InsertNewRow(obj);
231        }
232
233        if (locked == Guid.Empty) {
234          LockRow(obj.Id);
235          locked = obj.Id;
236        }
237
238        ConvertObj(obj, row);
239        dataAdapter.UpdateRow(row);
240
241        UnlockRow(locked);
242      }
243    }
244
245    public void Update(ObjT obj) {
246      ITransaction trans =
247        session.GetCurrentTransaction();
248      bool transactionExists = trans != null;
249      if (!transactionExists) {
250        trans = session.BeginTransaction();
251      }
252
253      try {
254        doUpdate(obj);
255      }
256      finally {
257        if (!transactionExists && trans != null) {
258          trans.Commit();
259        }
260      }
261    }
262
263    public virtual ObjT GetById(Guid id) {
264      return FindSingle(delegate() {
265        return dataAdapter.FindById(id);
266      });
267    }
268
269    public virtual ICollection<ObjT> GetAll() {
270      return new List<ObjT>(
271        FindMultiple(
272          new Selector(dataAdapter.FindAll)));
273    }
274
275    protected virtual bool doDelete(ObjT obj) {
276      bool success = false;
277
278      if (obj != null) {
279        LockRow(obj.Id);
280
281        RowT row =
282          GetRowById(obj.Id);
283
284        if (row != null) {
285          row.Delete();
286          dataAdapter.UpdateRow(row);
287
288          success = true;
289        }
290
291        UnlockRow(obj.Id);
292      }
293
294      return success;
295    }
296
297    public bool Delete(ObjT obj) {
298      ITransaction trans =
299        session.GetCurrentTransaction();
300      bool transactionExists = trans != null;
301      if (!transactionExists) {
302        trans = session.BeginTransaction();
303      }
304
305      try {
306        return doDelete(obj);
307      }
308      finally {
309        if (!transactionExists && trans != null) {
310          trans.Commit();
311        }
312      } 
313    }
314  }
315}
316
Note: See TracBrowser for help on using the repository browser.