Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3.3-Hive/sources/HeuristicLab.Hive/HeuristicLab.Hive.Server.LINQDataAccess/3.3/ContextFactory.cs @ 4424

Last change on this file since 4424 was 4424, checked in by cneumuel, 14 years ago
  • Added and updated License Information in every file
  • Sort and remove usings in every file
  • Deleted obsolete DataAccess.ADOHelper
  • Deleted some obsolete files
File size: 5.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.Collections.Generic;
24using System.Data.Linq;
25using System.Threading;
26using System.Transactions;
27using HeuristicLab.Hive.Contracts;
28using HeuristicLab.Hive.Server.DataAccess;
29using HeuristicLab.Hive.Server.LINQDataAccess.Properties;
30using HeuristicLab.Tracing;
31
32
33namespace HeuristicLab.Hive.Server.LINQDataAccess {
34  /// <summary>
35  /// This class handles creates one Context for each Thread which asks for one.
36  /// If one Thread calls GetContext several times, it always gets the same Context object.
37  /// A context object is removed from the cache when it is disposed.
38  ///
39  /// Every context has a DB-Transaction over its livetime. After using the context object
40  /// it has to be disposed in order to finish the corresponding transaction.
41  /// </summary>
42  class ContextFactory : IContextFactory {
43    private static object locker = new object();
44    private static IDictionary<int, HiveDataContext> contexts = new Dictionary<int, HiveDataContext>();
45    private static IDictionary<int, TransactionScope> transactions = new Dictionary<int, TransactionScope>();
46
47    private static IContextFactory instance = null;
48    public static IContextFactory Instance {
49      get {
50        if (instance == null)
51          instance = new ContextFactory();
52        return instance;
53      }
54    }
55
56    #region IContextManager Members
57
58    public IDisposable GetContext() {
59      return GetContext(true);
60    }
61
62    public IDisposable GetContext(bool withTransaction) {
63      lock (locker) {
64        int threadId = Thread.CurrentThread.ManagedThreadId;
65
66        if (contexts.ContainsKey(threadId)) {
67          Logger.Error("ERROR: Context for this Thread already defined. Will dispose it and then create a new one.");
68          RemoveContext();
69          RemoveAndCompleteTransaction();
70        }
71
72        DisposableHiveDataContext context = CreateContext();
73        context.OnDisposing += new EventHandler(context_OnDisposing);
74        contexts.Add(threadId, context);
75
76        if (withTransaction) {
77          TransactionScope transaction = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = ApplicationConstants.ISOLATION_LEVEL_SCOPE });
78          transactions.Add(threadId, transaction);
79        }
80        return context;
81      }
82    }
83
84    private static DisposableHiveDataContext CreateContext() {
85      return new DisposableHiveDataContext(Settings.Default.HeuristicLab_Hive_LinqConnectionString);
86    }
87
88    void context_OnDisposing(object sender, EventArgs e) {
89      lock (locker) {
90        RemoveContext();
91        RemoveAndCompleteTransaction();
92      }
93    }
94
95    public void RollbackTransaction() {
96      int threadId = Thread.CurrentThread.ManagedThreadId;
97
98      TransactionScope transaction = transactions[threadId];
99      transaction.Dispose();
100    }
101
102    public void RemoveContext() {
103      lock (locker) {
104        int threadId = Thread.CurrentThread.ManagedThreadId;
105
106        contexts.Remove(threadId);
107        // context gets disposed implicitly, when it is used as IDisposable
108      }
109    }
110
111    public void RemoveAndCompleteTransaction() {
112      lock (locker) {
113        int threadId = Thread.CurrentThread.ManagedThreadId;
114
115        // context does not always have an associated transaction
116        if (transactions.ContainsKey(threadId)) {
117          try {
118            transactions[threadId].Complete();
119            transactions[threadId].Dispose();
120          }
121          catch (Exception) { }
122          finally {
123            transactions.Remove(threadId);
124          }
125        }
126      }
127    }
128
129    public DataContext CurrentContext {
130      get {
131        lock (locker) {
132          int threadId = Thread.CurrentThread.ManagedThreadId;
133          if (contexts.ContainsKey(threadId)) {
134            return contexts[threadId];
135          } else {
136            return null;
137          }
138        }
139      }
140    }
141
142    #endregion
143  }
144
145  /// <summary>
146  /// Offers an event when it gets disposed
147  /// </summary>
148  class DisposableHiveDataContext : HiveDataContext {
149
150    public DisposableHiveDataContext(string connection) : base(connection) { }
151
152    protected override void Dispose(bool disposing) {
153      base.Dispose(disposing);
154      if (OnDisposing != null)
155        OnDisposing(this, new EventArgs());
156    }
157
158    public event EventHandler OnDisposing;
159  }
160}
Note: See TracBrowser for help on using the repository browser.