PDA

View Full Version : Shared Property


Anonymous
11-01-2004, 04:55 PM
Hi,
I would like to specify my connection string as a separate object in the config and then just reference that in each of my data access objects without having to write the entire connection string everytime. How would I do that?

Thanks,
Aaron

Rick Evans
11-01-2004, 10:37 PM
Hi Aaron

Well I daresay the approach described below ain't canon, but you could try the following... I don’t know what data technology you're using so I'll stick to using the ADO.NET support classes.

Lets start with the following configuration style file (saved as 'properties.xml' in the top level folder of my application); inside it I've defined a simple key/value pair that describes the connection string that I'm going to 'plug' into my various IDbConnection objects...

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<dao-properties>
<add key="connection.string" value="dsn=MyDSN;uid=sa;pwd=myPassword;"/>
</dao-properties>
</configuration>

Now lets take a look at the object definitions into which the previously defined connection string is going to be plugged...

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="objects" type="Spring.Context.Support.ApplicationContextHandler, Spring.Context" />
</configSections>
<objects>
<object name="dao.configurer" class="Spring.Objects.Factory.Config.PropertyPlaceholderC onfigurer, Spring.Core">
<property name="locations">
<list>
<value>properties.xml</value>
</list>
</property>
<property name="configSections">
<list>
<value>dao-properties</value>
</list>
</property>
</object>
<object name="myConnection" class="System.Data.Odbc.OdbcConnection, System.Data">
<property name="connectionstring">
<value>${connection.string}</value>
</property>
</object>
<object name="myOtherConnection" class="System.Data.Odbc.OdbcConnection, System.Data">
<property name="connectionstring">
<value>${connection.string}</value>
</property>
</object>
</objects>
</configuration>

Nothing too special here... apart from the object named 'dao.configurer' and those weird '${connection.string}' bits in the definition of my IDBConnection objects. The '${connection.string}' is a placeholder... it will be replaced with whatever the value of 'connection.string' is... we defined this value previously in the external 'properties.xml' file. This is all well and good, but how does the '${connection.string}' get replaced with the actual connection string value of 'dsn=MyDSN;uid=sa;pwd=myPassword;'?

The answer lies in the object definition called 'dao.configurer', which as you can see from the value of it's attendant 'class' attribute is an instance of the cunningly named 'PropertyPlaceholderConfigurer' class. The remit of the 'PropertyPlaceholderConfigurer' class is, strangely enough, to replace properties. What properties... well, the properties that it will load up are supplied as simple properties on it's object definition, namely 'Locations' and 'ConfigSections'. In the case of the one configured above, the location of the file containing the properties we want to load is 'properties.xml' and the section within said properties file is called 'dao-properties'. Shucks, I sure hope that makes sense.

The application code to demonstrate this looks like so...

IApplicationContext ctx
= ConfigurationSettings.GetConfig ("objects") as IApplicationContext;
System.Data.IDbConnection conn = ctx ["myConnection"] as System.Data.IDbConnection;
Console.WriteLine (conn.ConnectionString);

The 'PropertyPlaceholderConfigurer' class is special in that it implements the 'IObjectFactoryPostProcessor' interface... Spring.NET's IoC container automagically detects objects that implement this interface when the IApplicationContext is loaded, and lets these objects do any post processing that they might wish to do. In the case of the 'PropertyPlaceholderConfigurer' class, it replaces placeholder properties with actual values, so that (in our case) '${connection.string}' gets replaced with 'dsn=MyDSN;uid=sa;pwd=myPassword;'

Yeah, I think I can hear what you're gonna say... 'What! All that, just to plug in a connection string?! Cheers mate, but no thanks!'. :?

Sure, it's verbose... that's the price of flexibility. It does have the nice benefit that the 'properties.xml' file can have different (stricter) access rights from that of the object definition file, so that only your database admins are able to edit the connection strings (and thus safeguard the passwords).

There are other avenues to consider as well (at least one of them simpler), but I'd hate for Spring.NET to become the timtoady (TMTOWTDI) of .NET configuration so I'll leave it at that. Feel free to mail me or request those other avenues on this forum, I'll be happy to oblige :D

Ciao
Rick

P.S. I've left the scaffolding of the C# code a tad sparse... check out the main class of the MovieFinder (http://www.springframework.net/doc/reference/quickstarts.html) example application on the Spring.NET website for the details.

Anonymous
11-02-2004, 12:41 AM
Thanks a bunch Rick... makes sense. Along the same lines, I did have a question concerning Spring objects as singletons and IDbConnection: It seems like a bad idea to me to have 1 connection for my entire application… and I’ve seen in examples, including your previous post, using Spring to create a singleton connection object.



Thanks,

Aaron

Mark Pollack
11-02-2004, 05:08 PM
Hi,

Connection pooling is they way to go. What provider are you using? Most have some default connection pooling behavior which you can customize using the connection string. We are developing data access functionality in Spring.NET which will help out by removing the need for you to write boiler plate connection management code and exception handling - handling such sundry topics as always returning the connection to the pool etc. In the meantime, you will have to code the boiler plate code yourself, creating a new connection object with the same connection string, which under the covers will actually take a connection from the pool when you open it.

The following article (http://www.ondotnet.com/pub/a/dotnet/2004/02/09/connpool.html) and related references should be a good start. I've personally found the book ADO.NET Programming (http://www.manning.com/feldman) to be a valuable resource.


BTW, the nice thing about PropertyPlaceHolder is that some configuration information you want 'end-users' to change isn't mixed up with the 'wiring' of the application.


Hope this helps.

Cheers,
Mark

Anonymous
11-02-2004, 09:11 PM
I'm using the System.Data.SqlClient provider. I understand that I can configure connection pooling via data sources in the OS, but doesn't that only come into play when you are creating a NEW connection... rather than using the same singleton connection for your whole app. Unless I am missing something about how connections work.

Thanks,
Aaron

Mark Pollack
11-02-2004, 10:31 PM
Hi,

As far as I understand it, the pool is created based on the string you provide to the ctor of the connection. Two different strings, two pools - 100 connections with same string - same underlying pool. The 'real' connection used to speak to the DB isn't taken out of the pool and associated with the 'exposed' connection until you execute 'open'. If you have multiple threads you will want to have a different SqlConnection instances, all with the same connection string and not share the same SqlConnection object across threads. Depending on the design of your app, you can achieve this by either by sharing the connection string using dependency injection or declare the object not to be a singleton in Spring. (singleton="false" attribute) This way you get a new connection instance whenever it is referenced in the config file. In anycase, look into the pooling parameters and be sure to always open/close the SqlConnection object. Follow whatever other best practices you can get your hands on for ado.net usage!

Cheers,
Mark