ConnectionManager in RO/.NET

First off… thanks for the help thus far. As I proceed deeper into the conversion to RO/.NET I am now having an issues with the ConnectionManager. And of course it does not help being a newb with C#.

As the DA Server starts up in the main thread, I read some settings from an INI file and load the XML daConnections file. Followed by decrypting the password in each connectionstring, then storing the unencrypted password back into the connectionstring; At this point all appears well. and I can confirm that the connectionstrings are well formed.

Then I run a simple query from my interface. But when I check e.Connection.ConnectionString while in the BeforeAcquireConnection of the respective IMPL file, it is blank. If I include a new connection managers on the service, it complains about the connection manager already being registered.

Please advise. What am I doing wrong? I ultimately want each service to have its own schema, and each schema gets its own connection string. Within my RO for Delphi I imported the daConnection file when the server first stated, saving it as a TStringStream. Then simply grabbed that stream in the OnCreate of each service and imported into that services own CxnManager. I get the impression that with .NET only have ONE connection managers is allowed.

Some direction please…

Regards,
Monte Carver

Hello

By default ConnectionManager registers itself as a singleton. However it exposes a constructor that accepts Boolean parameter that indicates whether ConnectionManager instance being created should be registered as singleton or not. So you need to create ConenctionManager passing false to its constructor.

Also please note the following:

  • Re-instantiation of ConnectionManager on each service call is very ineffective in terms of performance. It would be much better to cache ConnectionManager instances and retrieve needed instance when the service is activated.
  • In case all your services are exactly the same and only their Schema and ConnectionManager are different you could consider to use only one service and to select needed ServiceSchema and ConnectionManager when the service instance is activated.

Hope that helps

The purpose of the BeforeAcquireConnection event is to allow to change name of the connection to be acquired. The connection itself is not yet acquired at the moment this event is triggered.

Acquired connection is available in the AfterAcquireConnection event.

Thanks for the insight. However when I do
this.daCxnMgr.Load();

I get
{“Object reference not set to an instance of an object.”}

Any suggestions? The connectionManager called daCxnMgr is NOT NULL

Please advise.
Monte Carverr

Hello Monte.

I am not opposed to using the “singleton” instance of the connection manager in the main thread. But when I attempt to open a dataset from the client using the connection manager from the main thread, It complains with error: “No connection manager has yet been registered”.

The problem happens if there is no registered ConnectionManager component. You can put this component anywhere on the server side.

And when I use a new ConnectionManger in the IMPL file, I get an error regarding name length cannot be zero.

After setting ConnectionManager component it is necessary to load corresponding schema connections using the next code:

this.connectionManager.Load();

Then client will be able to get data from the server side.

Thanks.

When attempting
this.connectionManager.Load();

I get {“Object reference not set to an instance of an object.”}
The connectionManager is not null. What am I doing wrong?

Also, I am needing to load the MyCxnMgr.daConnections, which I am doing using
         this.connectionManager.LoadFromFile( MyFullPath + “\MTCxnMgr.daConnections”));
I assume I do this before the Load() ?

Please advise.
Monte Carver

I believe I discovered the source of the problem. I modified the various aspects of the wizard created project to suite my fancy. In doing so, I modified the default daConnections project file from:
“WebSvcCCOK_B.daConnections"
to
"MTCxnMgr.daConnections”

This act raises the error I mentioned. So this begs the questions:

  1. Where in the project is the connectionManager so closely bound to the unit named WebSvcCCOK_B.daConnections?
  2. How do I change this relationship.
  3. Further, IF… I were to use multiple CxnMgr, how are these each associated with different files.
  4. Understand, that I am using the contents of WebSvcCCOK_B.daConnections only in design time, and wish to pull from a given file in runtime.

Again… thanks for the help.
Monte Carver

Also, it appears that after doing MyCxnMgr.LoadFromFile I do not need nor want to do MyCxnMgr.Load(), as it attempts to load the design time connections in addition to those from LoadFromFile, which is causing duplicates.

Please advise.

Monte

Hello Monte.

I believe I discovered the source of the problem. I modified the various aspects of the wizard created project to suite my fancy. In doing so, I modified the default daConnections project file from:
“WebSvcCCOK_B.daConnections”
to
“MTCxnMgr.daConnections”

Load method itself loads a Data Abstract connections file using the default mechanism, which looks in several places for a valid .daConnections file (Documentation | RemObjects Software):

as a .daConnnections file next to your application’s executable
as a .daConnnections resource in your application’s executable
If your application does not provide a custom DataAbstract.daConfig, either as file or as embedded resource, the call will fail with an exception.

So, as .daConnections file is renamed an exception is raised.

  1. Where in the project is the connectionManager so closely bound to the unit named WebSvcCCOK_B.daConnections?
  1. How do I change this relationship.

You need to use LoadFromFile(filepath) method instead which allows to get connection definitions from the specified file.

  1. Further, IF… I were to use multiple CxnMgr, how are these each associated with different files.
  1. Understand, that I am using the contents of WebSvcCCOK_B.daConnections only in design time, and wish to pull from a given file in runtime.

Using LoadFromFile(filepath) method you can set connection definitions dynamically setting different filepathes in runtime.

Also, it appears that after doing MyCxnMgr.LoadFromFile I do not need nor want to do MyCxnMgr.Load(), as it attempts to load the design time connections in addition to those from LoadFromFile, which is causing duplicates.

You don’t need to use Load() together with LoadFromFile() as they use the same .daConnections file to load. Please use LoadFromFile() instead.

Thanks.

Thank you for clarifying the connection problems!

Now that I am past that, I am next plagued with being unable to find a given schema. When I attempt to open a dataset from a client, the MT complains about being unable to find the given schema. So for example, I have a service called SvcQuote. In its IMPL I have defined its ServiceSchemaName as SvcQuote, to correspond with the unit SvcQuote.daSchema that is in the VisualStudio project. However the MT errors with “Cannot find schema SvcQuote”. I have tried naming the ServiceSchemaName = SvcQuote.daSchema. This has no effect.

Also, If I use MyCxnMgr.LoadFromFile vs MyCxnMgr.Load I get the exception "Length cannot be less than zero. Parameter name: length

Upon further digging, it appears this error stems from decrypting the password. If I don’t encrypt the password, then the LoadFromFile works. So… what in the following code is causing the length error?

// VARIABLES
            int i;
            bool lbool;
            string lCxnStr;
            string lPWord;
            string lDriverName = null;
            DataProviderInfo lProvInfo = null;
            DatabaseProfile lDBProfile = null;
            RemObjects.Common.Collections.CaseInsensitiveNameValueCollection lParamList = null;
            // END VARIABLE

for (i = 0; i <= this.daCxnMgr.ConnectionDefinitions.Count - 1; i++)
            {
                lCxnStr = this.daCxnMgr.ConnectionDefinitions[i].ConnectionString;
                lbool = RemObjects.DataAbstract.Server.ConnectionStringParser.Parse
                            (lCxnStr
                            , out lDriverName
                            , out lProvInfo
                            , out lDBProfile
                            , out lParamList
                             );
                lPWord = cRijndaelEncrypt.fxCrypt(lParamList[“PASSWORD”], false);
                lParamList[“PASSWORD”] = lPWord;
                lCxnStr = RemObjects.DataAbstract.Server.ConnectionStringParser.BuildProviderConnectionString(lProvInfo
                                                                                                   , lDBProfile
                                                                                                   , lParamList
                                                                                                   );
                this.daCxnMgr.ConnectionDefinitions[i].ConnectionString = lCxnStr;
            }

Please advise.

  1. How do I successfully load from a file, change the password in each connection string, then load to the manager?
  2. How does one successfully reference a given schema? In Delphi, it was a simple matter of placing a daSchema on a service. In .NET there appears to be some other requirement. Because apparently ServiceSchemaName is insufficient.

Please advise.
Monte

Hello Monte.

Now that I am past that, I am next plagued with being unable to find a given schema. When I attempt to open a dataset from a client, the MT complains about being unable to find the given schema. So for example, I have a service called SvcQuote. In its IMPL I have defined its ServiceSchemaName as SvcQuote, to correspond with the unit SvcQuote.daSchema that is in the VisualStudio project. However the MT errors with “Cannot find schema SvcQuote”. I have tried naming the ServiceSchemaName = SvcQuote.daSchema. This has no effect.

The problem could happens if there is mismatching in ServiceSchemaName or schema is not present on the server side. If all is well in the project, can you send us testcase to investigate it in details?

Upon further digging, it appears this error stems from decrypting the password. If I don’t encrypt the password, then the LoadFromFile works. So… what in the following code is causing the length error?

Unfortunately, I can’t reproduce the problem locally. The code you have provided works on my side. Any additional information or testcase will be helpful to reproduce the problem locally and provide more concrete solution.

Thanks in advance

I suspect you will find that all though the code appears to work, when you attempt to open a datatable from a client, that you will get the error “Length cannot be less than zero. Parameter name: length”.

So to duplicate the problem, please take the code I provided, and attempt to open a query. Then you will see the error.

Please advise
Monte Carver

Upon further thought, I have uploaded the entire project. In this way you can more easily reproduce my problem.

As I am a newbie to RODA .NET please advise as to what I might change in my architecture.

Regards,
Monte Carver

See Attached Project:
MTWebSvcB.7z (320.1 KB)

Hello Monte.

Thank you for the testcase. I have reproduced the problem. To solve it please change the line:
this.daCxnMgr.ConnectionDefinitions[i].ConnectionString = lCxnStr;
to:
this.daCxnMgr.ConnectionDefinitions[i].ConnectionString = String.Format("{0}?{1}",lDriverName,lCxnStr);

and rebuild the server.

Thanks.