Example E3086
Visible to All Users

How to reopen a broken connection when using a PostgreSQL database

Files to look at:

This example demonstrates how to create an IDataStore wrapper for the PostgreSqlConnectionProvider and implement the functionality for recreating broken connections.

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

Program.cs(vb)
C#
using System; using DevExpress.Xpo; using DevExpress.Xpo.DB; namespace B190497 { class Program { static void Main(string[] args) { SafePostgreSqlConnectionProvider.Register(); SafePostgreSqlConnectionProvider dataStore = new SafePostgreSqlConnectionProvider( "user id=postgres;password=admin;server=donchakDBFarm;database=XpoUnitTests;port=5434", AutoCreateOption.DatabaseAndSchema ); IDataLayer dal = new SimpleDataLayer(dataStore); int id = CreateData(dal); Console.WriteLine("restart the database, and press any key to continue .."); Console.ReadKey(); new Session(dal).GetObjectByKey<Person>(id); ((IDisposable)dataStore).Dispose(); dal.Dispose(); Console.WriteLine("done\npress any key to exit .."); Console.ReadKey(); } static int CreateData(IDataLayer dal) { using (UnitOfWork uow = new UnitOfWork()) { Person result = uow.FindObject<Person>(null); if (result == null) { result = new Person(uow); result.Name = "Uriah"; } uow.CommitChanges(); return result.Oid; } } } public class Person : XPObject { public Person(Session session) : base(session) { } string fName; public string Name { get { return fName; } set { SetPropertyValue<string>("Name", ref fName, value); } } } }
SafePostgreSqlConnectionProvider.cs(vb)
C#
using System; using System.Data; using DevExpress.Xpo.DB; using DevExpress.Xpo.DB.Exceptions; using System.Reflection; using System.Globalization; using DevExpress.Xpo.Helpers; using Npgsql; namespace B190497 { public class SafePostgreSqlConnectionProvider : IDataStore, IDisposable, ICommandChannel { PostgreSqlConnectionProvider InnerDataStore; IDbConnection Connection; string ConnectionString; AutoCreateOption AutoCreateOption; public static void Register() { DataStoreBase.RegisterDataStoreProvider(PostgreSqlConnectionProvider.XpoProviderTypeString, new DevExpress.Xpo.DB.Helpers.DataStoreCreationFromStringDelegate(CreateProviderFromString)); } public static IDataStore CreateProviderFromString(string connectionString, AutoCreateOption autoCreateOption, out IDisposable[] objectsToDisposeOnDisconnect) { SafePostgreSqlConnectionProvider rv = new SafePostgreSqlConnectionProvider(connectionString, autoCreateOption); objectsToDisposeOnDisconnect = new IDisposable[] { rv }; return rv; } public SafePostgreSqlConnectionProvider(string connectionString, AutoCreateOption autoCreateOption) { this.ConnectionString = connectionString; this.AutoCreateOption = autoCreateOption; DoReconnect(); } ~SafePostgreSqlConnectionProvider() { Dispose(false); } void DoReconnect() { DoDispose(false); Connection = PostgreSqlConnectionProvider.CreateConnection(ConnectionString); InnerDataStore = new PostgreSqlConnectionProvider(Connection, AutoCreateOption); } void DoDispose(bool closeConnection) { if (Connection != null) { if (closeConnection) { Connection.Close(); Connection.Dispose(); } Connection = null; } } protected virtual void Dispose(bool disposing) { if (disposing) DoDispose(true); } void HandleNullReferenceException(Exception ex) { if (ex == null) return; if (ex is NullReferenceException && InnerDataStore.Connection.State == ConnectionState.Open) { DoReconnect(); return; } NpgsqlException npgex = ex as NpgsqlException; if (npgex != null && npgex.Errors != null && InnerDataStore.Connection.State == ConnectionState.Open) { foreach (NpgsqlError error in npgex.Errors) { if (error.Message.Contains("broken")) { DoReconnect(); return; } } } throw ex; } AutoCreateOption IDataStore.AutoCreateOption { get { return InnerDataStore.AutoCreateOption; } } ModificationResult IDataStore.ModifyData(params ModificationStatement[] dmlStatements) { try { return InnerDataStore.ModifyData(dmlStatements); } catch (SqlExecutionErrorException ex) { HandleNullReferenceException(ex.InnerException); } return InnerDataStore.ModifyData(dmlStatements); } SelectedData IDataStore.SelectData(params SelectStatement[] selects) { try { return InnerDataStore.SelectData(selects); } catch (NullReferenceException ex) { HandleNullReferenceException(ex.InnerException); } return InnerDataStore.SelectData(selects); } UpdateSchemaResult IDataStore.UpdateSchema(bool dontCreateIfFirstTableNotExist, params DBTable[] tables) { try { return InnerDataStore.UpdateSchema(dontCreateIfFirstTableNotExist, tables); } catch (SqlExecutionErrorException ex) { HandleNullReferenceException(ex.InnerException); } return InnerDataStore.UpdateSchema(dontCreateIfFirstTableNotExist, tables); } void IDisposable.Dispose() { Dispose(true); GC.SuppressFinalize(this); } //T270757 public object Do(string command, object args) { return ((ICommandChannel)InnerDataStore).Do(command, args); } } }

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.