internal NpgsqlTransaction(NpgsqlConnection conn, IsolationLevel isolation) { _conn = conn; _isolation = isolation; StringBuilder commandText = new StringBuilder("BEGIN; SET TRANSACTION ISOLATION LEVEL "); if (isolation == IsolationLevel.RepeatableRead) { commandText.Append("REPEATABLE READ"); } else if ((isolation == IsolationLevel.Serializable) || (isolation == IsolationLevel.Snapshot)) { commandText.Append("SERIALIZABLE"); } else { // Set isolation level default to read committed. _isolation = IsolationLevel.ReadCommitted; commandText.Append("READ COMMITTED"); } commandText.Append(";"); NpgsqlCommand command = new NpgsqlCommand(commandText.ToString(), conn.Connector); command.ExecuteBlind(); _conn.Connector.Transaction = this; }
public override IEnumerable<IServerResponseObject> QueryEnum(NpgsqlConnector context, NpgsqlCommand command) { // Send the query request to backend. NpgsqlQuery.Send(command, context.Stream); context.Stream.Flush(); return ProcessBackendResponsesEnum(context, false); }
public static void Send(NpgsqlCommand command, Stream stream) { var commandStream = command.GetCommandStream(); commandStream.Position = 0; // Log the string being sent. //if (NpgsqlEventLog.Level >= LogLevel.Debug) //PGUtil.LogStringWritten(commandText.ToString()); // This method needs refactory. // The code below which deals with writing string to stream needs to be redone to use // PGUtil.WriteString() as before. The problem is that WriteString is using too much strings (concatenation). // Find a way to optimize that. // Tell to mediator what command is being sent. //TODO command.Connector.Mediator.SqlSent = command.CommandText; // Workaround for seek exceptions when running under ms.net. TODO: Check why Npgsql may be letting behind data in the stream. stream.Flush(); // Send the query to server. // Write the byte 'Q' to identify a query message. stream.WriteByte((byte)FrontEndMessageCode.Query); //Work out the encoding of the string (null-terminated) once and take the length from having done so //rather than doing so repeatedly. // Write message length. Int32 + string length + null terminator. PGUtil.WriteInt32(stream, 4 + (int)commandStream.Length + 1); var cms = commandStream as Revenj.Utility.ChunkedMemoryStream; if (cms != null) { cms.CopyTo(stream); stream.WriteByte(0); } else { commandStream.CopyTo(stream); stream.WriteByte(0); } Thread.Yield(); }
/// <summary> /// Opens the physical connection to the server. /// </summary> /// <remarks>Usually called by the RequestConnector /// Method of the connection pool manager.</remarks> internal void Open() { ServerVersion = null; // If Connection.ConnectionString specifies a protocol version, we will // not try to fall back to version 2 on failure. // Reset state to initialize new connector in pool. CurrentState = NpgsqlClosedState.Instance; // Get a raw connection, possibly SSL... CurrentState.Open(this); try { // Establish protocol communication and handle authentication... CurrentState.Startup(this); } catch (NpgsqlException) { throw; } // Change the state of connection to open and ready. State = ConnectionState.Open; CurrentState = NpgsqlReadyState.Instance; // Fall back to the old way, SELECT VERSION(). // This should not happen for protocol version 3+. if (ServerVersion == null) { using (NpgsqlCommand command = new NpgsqlCommand("set DATESTYLE TO ISO;select version();", this)) { ServerVersion = new Version(PGUtil.ExtractServerVersion((string)command.ExecuteScalar())); } } StringBuilder sbInit = new StringBuilder(); // Adjust client encoding. NpgsqlParameterStatus clientEncodingParam = null; if (!ServerParameters.TryGetValue("client_encoding", out clientEncodingParam) || !string.Equals(clientEncodingParam.ParameterValue, "UTF8", StringComparison.OrdinalIgnoreCase) && !string.Equals(clientEncodingParam.ParameterValue, "UNICODE", StringComparison.OrdinalIgnoreCase)) sbInit.AppendLine("SET CLIENT_ENCODING TO UTF8;"); if (!string.IsNullOrEmpty(settings.SearchPath)) { // TODO: Add proper message when finding a semicolon in search_path. // This semicolon could lead to a sql injection security hole as someone could write in connection string: // searchpath=public;delete from table; and it would be executed. if (settings.SearchPath.Contains(";")) { throw new InvalidOperationException(); } sbInit.AppendLine("SET SEARCH_PATH=" + settings.SearchPath + ";"); } if (!string.IsNullOrEmpty(settings.ApplicationName)) { if (!SupportsApplicationName) { //TODO //throw new InvalidOperationException(resman.GetString("Exception_ApplicationNameNotSupported")); throw new InvalidOperationException("ApplicationName not supported."); } if (settings.ApplicationName.Contains(";")) { throw new InvalidOperationException(); } sbInit.AppendLine("SET APPLICATION_NAME='" + settings.ApplicationName.Replace('\'', '-') + "';"); } /* * Try to set SSL negotiation to 0. As of 2010-03-29, recent problems in SSL library implementations made * postgresql to add a parameter to set a value when to do this renegotiation or 0 to disable it. * Currently, Npgsql has a problem with renegotiation so, we are trying to disable it here. * This only works on postgresql servers where the ssl renegotiation settings is supported of course. * See http://lists.pgfoundry.org/pipermail/npgsql-devel/2010-February/001065.html for more information. */ sbInit.AppendLine("SET ssl_renegotiation_limit=0;"); /* * Set precision digits to maximum value possible. For postgresql before 9 it was 2, after that, it is 3. * This way, we set first to 2 and then to 3. If there is an error because of 3, it will have been set to 2 at least. * Check bug report #1010992 for more information. */ sbInit.AppendLine("SET extra_float_digits=3;"); try { new NpgsqlCommand(sbInit.ToString(), this).ExecuteBlind(); } catch { foreach (var line in sbInit.ToString().Split(Environment.NewLine.ToCharArray())) { try { if (line.Length > 0) { new NpgsqlCommand(line, this).ExecuteBlind(); } } catch { } } } // Make a shallow copy of the type mapping that the connector will own. // It is possible that the connector may add types to its private // mapping that will not be valid to another connector, even // if connected to the same backend version. _oidToNameMapping = NpgsqlTypesHelper.CreateAndLoadInitialTypesMapping(this).Clone(); ProcessServerVersion(); // The connector is now fully initialized. Beyond this point, it is // safe to release it back to the pool rather than closing it. IsInitialized = true; }
//TODO: WTF!? /// <summary> /// This method checks if the connector is still ok. /// We try to send a simple query text, select 1 as ConnectionTest; /// </summary> internal Boolean IsValid() { try { // Here we use a fake NpgsqlCommand, just to send the test query string. var testValue = (ValidCounter++).ToString(); string compareValue = string.Empty; using (NpgsqlCommand cmd = new NpgsqlCommand("select '" + testValue + "'", this)) { compareValue = (string)cmd.ExecuteScalar(); } if (compareValue != testValue) return false; // Clear mediator. Mediator.ResetResponses(); this.RequireReadyForQuery = true; } catch { return false; } return true; }
///<summary> /// /// This method is reponsible to derive the command parameter list with values obtained from function definition. /// It clears the Parameters collection of command. Also, if there is any parameter type which is not supported by Npgsql, an InvalidOperationException will be thrown. /// Parameters name will be parameter1, parameter2, ... /// For while, only parameter name and NpgsqlDbType are obtained. ///</summary> /// <param name="command">NpgsqlCommand whose function parameters will be obtained.</param> public static void DeriveParameters(NpgsqlCommand command) { // Updated after 0.99.3 to support the optional existence of a name qualifying schema and case insensitivity when the schema ror procedure name do not contain a quote. // This fixed an incompatibility with NpgsqlCommand.CheckFunctionReturn(String ReturnType) String query = null; string procedureName = null; string schemaName = null; string[] fullName = command.CommandText.Split('.'); if (fullName.Length > 1 && fullName[0].Length > 0) { query = "select proargnames, proargtypes from pg_proc p left join pg_namespace n on p.pronamespace = n.oid where proname=:proname and n.nspname=:nspname"; schemaName = (fullName[0].IndexOf("\"") != -1) ? fullName[0] : fullName[0].ToLower(); procedureName = (fullName[1].IndexOf("\"") != -1) ? fullName[1] : fullName[1].ToLower(); } else { query = "select proargnames, proargtypes from pg_proc where proname = :proname"; procedureName = (fullName[0].IndexOf("\"") != -1) ? fullName[0] : fullName[0].ToLower(); } using (NpgsqlCommand c = new NpgsqlCommand(query, command.Connection)) { c.Parameters.Add(new NpgsqlParameter("proname", NpgsqlDbType.Text)); c.Parameters[0].Value = procedureName.Replace("\"", "").Trim(); if (fullName.Length > 1 && !String.IsNullOrEmpty(schemaName)) { NpgsqlParameter prm = c.Parameters.Add(new NpgsqlParameter("nspname", NpgsqlDbType.Text)); prm.Value = schemaName.Replace("\"", "").Trim(); } String[] names = null; String[] types = null; using (NpgsqlDataReader rdr = c.ExecuteReader(CommandBehavior.SingleRow | CommandBehavior.SingleResult)) { if (rdr.Read()) { if (!rdr.IsDBNull(0)) names = rdr.GetValue(0) as String[]; if (!rdr.IsDBNull(1)) types = rdr.GetString(1).Split(); } } if (types == null) { throw new InvalidOperationException( String.Format(resman.GetString("Exception_InvalidFunctionName"), command.CommandText)); } command.Parameters.Clear(); for (Int32 i = 0; i < types.Length; i++) { // skip parameter if type string is empty // empty parameter lists can cause this if (!string.IsNullOrEmpty(types[i])) { NpgsqlBackendTypeInfo typeInfo = null; if (!c.Connector.OidToNameMapping.TryGetValue(int.Parse(types[i]), out typeInfo)) { command.Parameters.Clear(); throw new InvalidOperationException(String.Format("Invalid parameter type: {0}", types[i])); } if (names != null && i < names.Length) command.Parameters.Add(new NpgsqlParameter(":" + names[i], typeInfo.NpgsqlDbType)); else command.Parameters.Add(new NpgsqlParameter("parameter" + (i + 1).ToString(), typeInfo.NpgsqlDbType)); } } } }
private NpgsqlCommand BuildCommand(StringBuilder query, string[] restrictions, bool addWhere, params string[] names) { NpgsqlCommand command = new NpgsqlCommand(); if (restrictions != null && names != null) { for (int i = 0; i < restrictions.Length && i < names.Length; ++i) { if (restrictions[i] != null && restrictions[i].Length != 0) { if (addWhere) { query.Append(" WHERE "); addWhere = false; } else { query.Append(" AND "); } string paramName = RemoveSpecialChars(names[i]); query.AppendFormat("{0} = :{1}", names[i], paramName); command.Parameters.Add(new NpgsqlParameter(paramName, restrictions[i])); } } } command.CommandText = query.ToString(); command.Connection = _connection; return command; }
/// <summary> /// Create a new command based on this one. /// </summary> /// <returns>A new NpgsqlCommand object.</returns> public NpgsqlCommand Clone() { // TODO: Add consistency checks. NpgsqlCommand clone = new NpgsqlCommand(CommandText, Connection, Transaction); clone.CommandTimeout = CommandTimeout; clone.CommandType = CommandType; clone.DesignTimeVisible = DesignTimeVisible; if (ExpectedTypes != null) { clone.ExpectedTypes = (Type[])ExpectedTypes.Clone(); } foreach (NpgsqlParameter parameter in Parameters) { clone.Parameters.Add(parameter.Clone()); } return clone; }
internal void ReleaseRegisteredListen() { //Query(new NpgsqlCommand("unlisten *", this)); using (NpgsqlCommand cmd = new NpgsqlCommand("unlisten *", this)) { Query(cmd); } }
internal IEnumerable<IServerResponseObject> QueryEnum(NpgsqlCommand queryCommand) { if (CurrentReader != null) { if (!CurrentReader._cleanedUp) { throw new InvalidOperationException( "There is already an open DataReader associated with this Command which must be closed first."); } CurrentReader.Close(); } return CurrentState.QueryEnum(this, queryCommand); }
/* * Constructs the LargeObject API. * * <p><b>Important Notice</b> * <br>This method should only be called by org.postgresql.Connection * * <p>There should only be one LargeObjectManager per Connection. The * org.postgresql.Connection class keeps track of the various extension API's * and it's advised you use those to gain access, and not going direct. */ public LargeObjectManager(NpgsqlConnection conn) { // We need Fastpath to do anything // Now get the function oid's for the api // // This is an example of Fastpath.addFunctions(); // //String sql; StringBuilder sql = null; try { sql = new StringBuilder(); if (conn.PostgreSqlVersion > new Version(7, 3, 0)) { sql.Append("SELECT p.proname,p.oid "); sql.Append(" FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "); sql.Append(" WHERE p.pronamespace=n.oid AND n.nspname='pg_catalog' AND ("); } else { sql.Append("SELECT proname,oid FROM pg_proc WHERE "); } sql.Append(" proname = 'lo_open'"); sql.Append(" or proname = 'lo_close'"); sql.Append(" or proname = 'lo_creat'"); sql.Append(" or proname = 'lo_unlink'"); sql.Append(" or proname = 'lo_lseek'"); sql.Append(" or proname = 'lo_tell'"); sql.Append(" or proname = 'loread'"); sql.Append(" or proname = 'lowrite'"); if (conn.PostgreSqlVersion > new Version(7, 3, 0)) { sql.Append(")"); } using (IDbCommand cmd = new NpgsqlCommand(sql.ToString())) { cmd.Connection = conn; this.fp = new Fastpath(conn, conn.Connector.Stream); using (IDataReader res = cmd.ExecuteReader()) { if (res == null) { throw new NpgsqlException("postgresql.lo.init"); } fp.AddFunctions(res); } } } finally { sql = null; } }
public void CommitTransaction() { NpgsqlConnection connection = GetConnection(); NpgsqlCommand command = null; if (_prepared) { command = new NpgsqlCommand(string.Format("COMMIT PREPARED '{0}'", _txName), connection); } else { command = new NpgsqlCommand("COMMIT", connection); } command.ExecuteBlind(); }
public void RollbackTransaction() { NpgsqlConnection connection = GetConnection(); NpgsqlCommand command = null; if (_prepared) { command = new NpgsqlCommand(string.Format("ROLLBACK PREPARED '{0}'", _txName), connection); } else { command = new NpgsqlCommand("ROLLBACK", connection); } command.ExecuteBlind(); }
public void PrepareTransaction() { if (!_prepared) { NpgsqlConnection connection = GetConnection(); NpgsqlCommand command = new NpgsqlCommand(string.Format("PREPARE TRANSACTION '{0}'", _txName), connection); command.ExecuteBlind(); _prepared = true; } }
/// <summary> /// Given command is executed upon Start() and all requested copy data is written to toStream immediately. /// </summary> public NpgsqlCopyOut(NpgsqlCommand cmd, NpgsqlConnection conn, Stream toStream) { _context = conn.Connector; _cmd = cmd; _copyStream = toStream; }
/// <summary> /// Given command is run upon Start(), after which CopyStream provides data from database as requested in the query. /// </summary> public NpgsqlCopyOut(NpgsqlCommand cmd, NpgsqlConnection conn) : this(cmd, conn, null) { }
internal ForwardsOnlyDataReader GetReader(CommandBehavior cb) { try { CheckConnectionState(); var connector = Connector; if (PreparedQuery != null) connector.PrepareOrAdd(PreparedQuery, PreparedParams, text); // reset any responses just before getting new ones connector.Mediator.ResetResponses(); // Set command timeout. connector.Mediator.CommandTimeout = CommandTimeout; using (connector.BlockNotificationThread()) { ForwardsOnlyDataReader reader; if (parse == null) { reader = new ForwardsOnlyDataReader(connector.QueryEnum(this), cb, this, connector.BlockNotificationThread(), false); if (type == CommandType.StoredProcedure && reader.FieldCount == 1 && reader.GetDataTypeName(0) == "refcursor") { // When a function returns a sole column of refcursor, transparently // FETCH ALL from every such cursor and return those results. StringBuilder sb = new StringBuilder(); while (reader.Read()) { sb.Append("fetch all from \"").Append(reader.GetString(0)).Append("\";"); } sb.Append(";"); // Just in case the list of cursors is empty. //reader = new NpgsqlCommand(sb.ToString(), Connection).GetReader(reader._behavior); // Passthrough the commandtimeout to the inner command, so user can also control its timeout. // TODO: Check if there is a better way to handle that. NpgsqlCommand c = new NpgsqlCommand(sb.ToString(), Connection); c.CommandTimeout = this.CommandTimeout; reader = c.GetReader(reader._behavior); } } else { BindParameters(); reader = new ForwardsOnlyDataReader(connector.ExecuteEnum(new NpgsqlExecute(bind.PortalName, 0)), cb, this, connector.BlockNotificationThread(), true); } return reader; } } catch (IOException ex) { throw ClearPoolAndCreateException(ex); } }
internal void PrepareOrAdd(string planName, string types, string query) { if (!CachedPlans.Contains(planName)) { using (NpgsqlCommand cmd = new NpgsqlCommand("PREPARE \"" + planName + "\"(" + types + ") AS " + query, this)) Query(cmd); CachedPlans.Add(planName); } }
// State internal void Query(NpgsqlCommand queryCommand) { CurrentState.Query(this, queryCommand); }
public virtual void FunctionCall(NpgsqlConnector context, NpgsqlCommand command) { throw new InvalidOperationException("Internal Error! " + this); }
/// <summary> /// This method is responsible to release all portals used by this Connector. /// </summary> internal void ReleasePlansPortals() { Int32 i = 0; if (_planIndex > 0) { for (i = 1; i <= _planIndex; i++) { try { //Query(new NpgsqlCommand(String.Format("deallocate \"{0}\";", _planNamePrefix + i), this)); using (NpgsqlCommand cmd = new NpgsqlCommand(String.Format("deallocate \"{0}\";", _planNamePrefix + i.ToString()), this)) { Query(cmd); } } // Ignore any error which may occur when releasing portals as this portal name may not be valid anymore. i.e.: the portal name was used on a prepared query which had errors. catch { } } } foreach (var cp in CachedPlans) { try { using (NpgsqlCommand cmd = new NpgsqlCommand("deallocate \"" + cp + "\";", this)) Query(cmd); } // Ignore any error which may occur when releasing portals as this portal name may not be valid anymore. i.e.: the portal name was used on a prepared query which had errors. catch { } } CachedPlans.Clear(); _portalIndex = 0; _planIndex = 0; }
public virtual IEnumerable<IServerResponseObject> QueryEnum(NpgsqlConnector context, NpgsqlCommand command) { throw new InvalidOperationException("Internal Error! " + this); }
/// <summary> /// Rolls back a transaction from a pending state. /// </summary> public override void Rollback() { CheckDisposed(); if (_conn == null) { throw new InvalidOperationException(Exception_NoTransaction); } NpgsqlCommand command = new NpgsqlCommand("ROLLBACK", _conn.Connector); command.ExecuteBlind(); _conn.Connector.Transaction = null; _conn = null; }
private Boolean CheckFunctionNeedsColumnDefinitionList() { // If and only if a function returns "record" and has no OUT ("o" in proargmodes), INOUT ("b"), or TABLE // ("t") return arguments to characterize the result columns, we must provide a column definition list. // See http://pgfoundry.org/forum/forum.php?thread_id=1075&forum_id=519 // We would use our Output and InputOutput parameters to construct that column definition list. If we have // no such parameters, skip the check: we could only construct "AS ()", which yields a syntax error. // Updated after 0.99.3 to support the optional existence of a name qualifying schema and allow for case insensitivity // when the schema or procedure name do not contain a quote. // The hard-coded schema name 'public' was replaced with code that uses schema as a qualifier, only if it is provided. String returnRecordQuery; StringBuilder parameterTypes = new StringBuilder(""); // Process parameters Boolean seenDef = false; foreach (NpgsqlParameter p in Parameters) { if ((p.Direction == ParameterDirection.Input) || (p.Direction == ParameterDirection.InputOutput)) { parameterTypes.Append(Connection.Connector.OidToNameMapping[p.TypeInfo.Name].OID.ToString() + " "); } if ((p.Direction == ParameterDirection.Output) || (p.Direction == ParameterDirection.InputOutput)) { seenDef = true; } } if (!seenDef) { return false; } // Process schema name. String schemaName = String.Empty; String procedureName = String.Empty; String[] fullName = CommandText.Split('.'); String predicate = "prorettype = ( select oid from pg_type where typname = 'record' ) " + "and proargtypes=:proargtypes and proname=:proname " // proargmodes && array['o','b','t']::"char"[] performs just as well, but it requires PostgreSQL 8.2. + "and ('o' = any (proargmodes) OR 'b' = any (proargmodes) OR 't' = any (proargmodes)) is not true"; if (fullName.Length == 2) { returnRecordQuery = "select count(*) > 0 from pg_proc p left join pg_namespace n on p.pronamespace = n.oid where " + predicate + " and n.nspname=:nspname"; schemaName = (fullName[0].IndexOf("\"") != -1) ? fullName[0] : fullName[0].ToLower(); procedureName = (fullName[1].IndexOf("\"") != -1) ? fullName[1] : fullName[1].ToLower(); } else { // Instead of defaulting don't use the nspname, as an alternative, query pg_proc and pg_namespace to try and determine the nspname. //schemaName = "public"; // This was removed after build 0.99.3 because the assumption that a function is in public is often incorrect. returnRecordQuery = "select count(*) > 0 from pg_proc p where " + predicate; procedureName = (CommandText.IndexOf("\"") != -1) ? CommandText : CommandText.ToLower(); } bool ret; using (NpgsqlCommand c = new NpgsqlCommand(returnRecordQuery, Connection)) { c.Parameters.Add(new NpgsqlParameter("proargtypes", NpgsqlDbType.Oidvector)); c.Parameters.Add(new NpgsqlParameter("proname", NpgsqlDbType.Name)); c.Parameters[0].Value = parameterTypes.ToString(); c.Parameters[1].Value = procedureName; if (schemaName != null && schemaName.Length > 0) { c.Parameters.Add(new NpgsqlParameter("nspname", NpgsqlDbType.Name)); c.Parameters[2].Value = schemaName; } ret = (Boolean)c.ExecuteScalar(); } // reset any responses just before getting new ones m_Connector.Mediator.ResetResponses(); // Set command timeout. m_Connector.Mediator.CommandTimeout = CommandTimeout; return ret; }
public void Query(NpgsqlConnector context, NpgsqlCommand command) { IterateThroughAllResponses(QueryEnum(context, command)); }
/// <summary> /// Creates a transaction save point. /// </summary> public void Save(String savePointName) { CheckDisposed(); if (_conn == null) { throw new InvalidOperationException(Exception_NoTransaction); } if (!_conn.Connector.SupportsSavepoint) { throw new InvalidOperationException(Exception_SavePointNotSupported); } if (savePointName.Contains(";")) { throw new InvalidOperationException(Exception_SavePointWithSemicolon); } NpgsqlCommand command = new NpgsqlCommand("SAVEPOINT " + savePointName, _conn.Connector); command.ExecuteBlind(); }
public void TestNotify(NpgsqlConnector context) { //ZA Hnotifytest CNOTIFY Z //Qlisten notifytest;notify notifytest; Stream stm = context.Stream; string uuidString = "uuid" + Guid.NewGuid().ToString("N"); PGUtil.WriteString("Qlisten " + uuidString + ";notify " + uuidString + ";", stm); Queue<byte> buffer = new Queue<byte>(); byte[] convertBuffer = new byte[36]; for (; ; ) { int newByte = stm.ReadByte(); if (newByte == -1) { throw new EndOfStreamException(); } buffer.Enqueue((byte)newByte); if (buffer.Count > 35) { buffer.CopyTo(convertBuffer, 0); if (ENCODING_UTF8.GetString(convertBuffer) == uuidString) { for (; ; ) { switch (stm.ReadByte()) { case -1: throw new EndOfStreamException(); case 'Z': //context.Query(new NpgsqlCommand("UNLISTEN *", context)); using (NpgsqlCommand cmd = new NpgsqlCommand("UNLISTEN *", context)) { context.Query(cmd); } return; } } } else { buffer.Dequeue(); } } } }
public string CheckParameter(string paramName) { NpgsqlParameterStatus ps = null; if (_serverParameters.TryGetValue(paramName, out ps)) return ps.ParameterValue; try { using (NpgsqlCommand cmd = new NpgsqlCommand("show " + paramName, this)) { string paramValue = (string)cmd.ExecuteScalar(); AddParameterStatus(new NpgsqlParameterStatus(paramName, paramValue)); return paramValue; } } /* * In case of problems with the command above, we simply return null in order to * say we don't support it. */ catch (NpgsqlException) { return null; } /* * Original catch handler by Jon Hanna. * 7.3 version doesn't support error code. Only 7.4+ * catch(NpgsqlException ne) { if(ne.Code == "42704")//unrecognized configuration parameter return null; else throw; }*/ }
public NpgsqlQuery(NpgsqlCommand command) { _command = command; }
public NpgsqlDataAdapter(NpgsqlCommand selectCommand) { SelectCommand = selectCommand; }