My application hit an OutOfMemoryException. That's why I attached a memory profiler to find out that the problem was caused by dotConnect for ProsreSQL. I'm using version 4.95.190.
I used the following code to narrow the problem down to dotConnect.
Code: Select all
using System;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Threading;
namespace ProveDotConnectBug
{
internal class Program
{
private enum TestEnum
{
TestA,
TestB,
TestC,
TestD,
TestE,
TestF,
}
private Random mRandom;
private TestEnum[] mEnumValues;
private DbCommand mCommand;
private static void Main(string[] args)
{
Program program = new Program();
program.Run();
}
private Program()
{
mRandom = new Random(DateTime.Now.Millisecond);
mEnumValues = (TestEnum[])Enum.GetValues(typeof(TestEnum));
DbProviderFactory factory = DbProviderFactories.GetFactory(@"Devart.Data.PostgreSql");
DbConnection connection = factory.CreateConnection();
connection.ConnectionString = @"Host=localhost;Database=testdb;User Id=testuser;Password=secret;Protocol=2;Unicode=true;";
connection.Open();
mCommand = connection.CreateCommand();
mCommand.CommandText = @"testfunction";
mCommand.CommandType = CommandType.StoredProcedure;
AddParameter(mCommand, @"f1", DbType.Int32);
AddParameter(mCommand, @"f2", DbType.String);
AddParameter(mCommand, @"f3", DbType.Boolean);
AddParameter(mCommand, @"f4", DbType.DateTime);
mCommand.Prepare(); // This statement causes the application to leak memory!
}
private void Run()
{
long previous = -1;
while (true)
{
mCommand.Parameters[@"f1"].Value = mRandom.Next(int.MinValue, int.MaxValue);
mCommand.Parameters[@"f2"].Value = mEnumValues[mRandom.Next(mEnumValues.Length - 1)].ToString();
mCommand.Parameters[@"f3"].Value = (mRandom.Next(1) > 0);
mCommand.Parameters[@"f4"].Value = DateTime.Now;
long current = (long)mCommand.ExecuteScalar();
Debug.Assert(current > previous);
previous = current;
Thread.Sleep(50);
}
}
private static void AddParameter(DbCommand command, string name, DbType type)
{
DbParameter parameter = command.CreateParameter();
parameter.ParameterName = name;
parameter.DbType = type;
command.Parameters.Add(parameter);
}
}
}
Code: Select all
CREATE SEQUENCE testsequence INCREMENT 1 START 1;
CREATE TABLE testtable
(
id bigint NOT NULL DEFAULT nextval('testsequence'),
field1 integer,
field2 character varying(100) NOT NULL,
field3 boolean NOT NULL,
field4 timestamp without time zone,
CONSTRAINT testprimarykey PRIMARY KEY (id)
);
CREATE OR REPLACE FUNCTION testfunction(f1 integer, f2 character varying, f3 boolean, f4 timestamp without time zone)
RETURNS bigint AS
$$
DECLARE
res bigint;
BEGIN
INSERT INTO testtable(id,field1,field2,field3,field4) VALUES(DEFAULT,f1,f2,f3,f4) RETURNING id INTO STRICT res;
RETURN res;
END;
$$
LANGUAGE plpgsql VOLATILE;
What I also noticed is that when I change the code to use protocol version 3, the problem is not there (even when the Prepare() is in place)
To me this seems like a bug.
Regards,
Ruud