Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Hive.Server.ADODataAccess/DataAdapterBase.cs @ 1197

Last change on this file since 1197 was 1175, checked in by svonolfe, 16 years ago

Refactored DAL, avoided possible race conditions (#372)

File size: 5.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.Linq;
26using System.Text;
27using HeuristicLab.Hive.Contracts.BusinessObjects;
28using System.Threading;
29
30namespace HeuristicLab.Hive.Server.ADODataAccess {
31  abstract class DataAdapterBase<AdapterT, ObjT, RowT>
32    where AdapterT : new()
33    where RowT : System.Data.DataRow
34    where ObjT : IHiveObject, new() {
35
36    private static Mutex lockersMutex =
37      new Mutex();
38
39    private static IDictionary<object, Mutex> lockers =
40      new Dictionary<object, Mutex>();
41
42    private static IDictionary<object, int> lockCount =
43      new Dictionary<object, int>();
44
45    protected void LockRow(object id) {
46      Mutex rowLock = null;
47
48      /////begin critical section////
49      lockersMutex.WaitOne();
50
51      if (!lockers.ContainsKey(id)) {
52        lockers[id] = new Mutex();
53        lockCount[id] = 0;
54      }
55      rowLock = lockers[id];
56      lockCount[id]++;
57     
58      lockersMutex.ReleaseMutex();
59      /////end critical section////
60
61      rowLock.WaitOne();
62    }
63
64    protected void UnlockRow(object id) {
65      Mutex rowLock = lockers[id];
66      rowLock.ReleaseMutex();
67
68      /////begin critical section////
69      lockersMutex.WaitOne();
70
71      lockCount[id]--;
72      if (lockCount[id] == 0)
73        lockers.Remove(id);
74
75      lockersMutex.ReleaseMutex();
76      /////end critical section////
77    }
78   
79    protected AdapterT Adapter {
80      get {
81        return new AdapterT();
82      }
83    }
84
85    #region Abstract methods
86    protected abstract RowT ConvertObj(ObjT obj, RowT row);
87
88    protected abstract ObjT ConvertRow(RowT row, ObjT obj);
89
90    protected abstract RowT InsertNewRow(ObjT obj);
91
92    protected abstract void UpdateRow(RowT row);
93
94    protected abstract IEnumerable<RowT> FindById(long id);
95
96    protected abstract IEnumerable<RowT> FindAll();
97    #endregion
98
99    protected delegate IEnumerable<RowT> Selector();
100
101    protected ObjT Convert(RowT row, ObjT obj) {
102      try {
103        obj = ConvertRow(row, obj);
104        return obj;
105      }
106      catch (DeletedRowInaccessibleException) {
107        return default(ObjT);
108      }
109      catch (RowNotInTableException) {
110        return default(ObjT);
111      }
112    }
113
114    protected virtual RowT FindSingleRow(Selector selector) {
115      RowT row = default(RowT);
116
117      IEnumerable<RowT> found =
118        selector();
119
120      if (found.Count<RowT>() == 1)
121        row = found.First<RowT>();
122
123      return row;
124    }
125
126    protected virtual ObjT FindSingle(Selector selector) {
127      RowT row = FindSingleRow(selector);
128
129      if (row != null) {
130        ObjT obj = new ObjT();
131        obj = Convert(row, obj);
132
133        return obj;
134      } else {
135        return default(ObjT);
136      }
137    }
138
139    protected virtual ICollection<ObjT> FindMultiple(Selector selector) {
140      IEnumerable<RowT> found =
141        selector();
142
143      IList<ObjT> result =
144        new List<ObjT>();
145
146      foreach (RowT row in found) {
147        ObjT obj = new ObjT();
148        obj = Convert(row, obj);
149        if(obj != null)
150          result.Add(obj);
151      }
152
153      return result;
154    }
155
156    protected virtual RowT GetRowById(long id) {
157      return FindSingleRow(
158        delegate() {
159          return FindById(id);
160        });
161    }
162
163    public virtual void Update(ObjT obj) {
164      if (obj != null) {
165        RowT row = null;
166        long locked = default(long);
167       
168        if (obj.Id != default(long)) {
169           LockRow(obj.Id);
170           locked = obj.Id;
171
172           row = GetRowById(obj.Id);
173        }         
174
175        if (row == null) {
176          row = InsertNewRow(obj);
177          UpdateRow(row);
178
179          obj.Id = (long)row[row.Table.PrimaryKey[0]];
180        }
181
182        if (locked == default(long)) {
183          LockRow(obj.Id);
184          locked = obj.Id;
185        }
186
187        ConvertObj(obj, row);
188        UpdateRow(row);
189
190        UnlockRow(locked);
191      }
192    }
193
194    public virtual ObjT GetById(long id) {
195      return FindSingle(delegate() {
196        return FindById(id);
197      });
198    }
199
200    public virtual ICollection<ObjT> GetAll() {
201      return new List<ObjT>(
202        FindMultiple(
203          new Selector(FindAll)));
204    }
205
206    public virtual bool Delete(ObjT obj) {
207      bool success = false;
208     
209      if (obj != null) {
210        LockRow(obj.Id);
211
212        RowT row =
213          GetRowById(obj.Id);
214
215        if (row != null) {
216          row.Delete();
217          UpdateRow(row);
218
219          success = true;
220        }
221
222        UnlockRow(obj.Id);
223      }
224
225      return success;
226    }
227  }
228}
229
Note: See TracBrowser for help on using the repository browser.