D'Arcy from Winnipeg
Solution Architecture, Business & Entrepreneurship, Microsoft, and Adoption

Connection Strings, DAL's, Architecture, and Application Context

Sunday, January 20, 2008 12:39 AM

Back in December, I had a blog post around Sub Sonic and how I wished there was a separation between the UI and DAL...to which many people didn't really understand what I was asking for or what I was trying to do. And in turn, I realized that my issue had more to do with how ASP.NET in general is structured and not any particular framework (i.e. Sub Sonic) which just play in the sandbox their given.

.NET gains a lot of its power from how flexible it is, and how much leeway we as developers have in creating solutions with it. It is totally possible for us to create a fully data-aware, interactive, business application without writing any code and using all the designers drag and drop controls for everything from setting up the UI to configuring our database connections, to binding and manipulating data. But just because you can doesn't mean you *should*. For small applications, prototypes, or one-offs that you know will never grow, this is fine...or is it? Should we be ok with cutting architecture corners in the name of quick-fixing an app?

My opinion is that we should not; that many of the issues we face in maintaining our applications could be avoided if we followed proper architecture guidelines. I also don't think that enforcing this idea adds any amount of extra time to a project, especially when you gauge it against what happens afterwards when change requests flood in and teams have to try and update an application without breaking it in the process (been there, done that).

So let's get back to ASP.NET. The issue I had originally, and still do, is with the idea of the connection strings being accessed from the web.config file. The argument some made was that all code, because its being run as part of an overall ASP.NET application, should be considered the same *context*...which in this case is under ASP.NET. Therefore any code that accesses your data access layer should retrieve that value from the web applications config file. The problem however is that under this model there's nothing stopping code from the UI or other code that's part of this same context to use that value as well. Temptation can set in ("Oh, we don't need to write a whole class and access it to get this data...we'll just throw a sql connection object on the webform and bind it that way").

So by putting the connection string in the web.config file, you've now coupled your application with a database as well as a database implementation. If the database vendor changes, then you update the DAL as well as the config file so the DAL works property (i.e. you switch from SQL to Oracle).

"Well D'Arcy, what would you propose as a solution to this if its such a big deal?"

One option would be to store the database information as part of the config file for the DAL component.

Waaaait a second...this isn't possible though! Even if you do create a config file for the DAL, any configuration requests will default to the web.config file and effectively make any DLL configuration specific settings mute. At least, that's what most people will tell you.

The reality is that there is a way to add configuration values to your assembly...but there's a slight catch. In an assembly project you can add settings to the settings file. This in turn gets output to an app.config file within your assembly. Upon compiling, the values end up being written within your assembly, and your code can access them REGARDLESS of the "context" that its running in.

This means that none of your code outside your DAL have any clue as to what database is accessed, what type of database it is, etc. Everything goes through the DAL...everything is encapsulated.

Now here's where the discussion turns religious to an extent. The act of using the Settings file is a few steps up from hardcoding a value into your code and accessing it, isn't it? I mean, it's not actually reading from a config file at run time, its compiling the values directly into your assembly. But let's think through some realities here:

Connection String stored in....

Assembly Settings File

Pro:
- The value is accessible to the assembly without needing to reference the application in context's config file
- All database interaction is abstracted away from the UI and other layers consuming the DAL
- Switching database providers is merely replacing an assembly; no other settings at the app level are required

Cons:
- Changes to the configuration file will require a re-build of the project
- Unless you obfiscate your assembly, tools like reflector can view the values within the code

Web.Config File

Pro:
- Value is easily accessible and can be altered quickly if kept in plain text mode...which they shouldn't be in though.
- Code from within the web application context can access those values

Cons:
- Changes to the connection string value will require the conn-string portion of the file to be re-encrypted (you DO encrypt all your sensitive data in your web.config file don't you?)
- Code needs to know what names are associated with the configuration files
- Code from within the web application context can access those values (double edged sword)

Because your code needs to be aware of the config value names, its now coupled with your UI code...doesn't matter if you've split it out into separate assemblies. Now, what if you wanted to re-use that assembly in a Windows app, or a Mobile app? You better make sure you re-created those variable names properly in your application.config file. So now not only is your assembly coupled to your app, but any application that ends up using that assembly is coupled to each other!

I guess what I'm trying to figure out is why so many consider hard coding values a horrible thing, and yet all we're really doing with config files is creating a less-secure place to store values that we'd otherwise hard code in *and* handcuff our assemblies to our UI implementation. Config files are becoming a dumping ground for any setting that needs to be available across *all* tiers and not just the UI. Assemblies solved the DLL Hell problem, but config files seem to be the next evolution in .ini files.

Anyway, I wanted to post something that better explained what it was I was searching for in my earlier posts, and I hope this answered that. Feel free to post your thoughts, I look forward to them.

D




Feedback

# re: Connection Strings, DAL's, Architecture, and Application Context

{DL: Kent was getting an error when trying to post his comment, so he emailed it to me. I wanted to add it back here as he's got some great thoughts}

D'Arcy - I'm confused. This post has nothing to do with Justice Gray or the GeeksWithBlogs leaderboard. There must be a problem with your posting software.

For the majority of my apps, especially lately, I don't really see a need for what you're suggesting (or at least what I read into what you're suggesting). The main reason is re-use. I rarely (currently) re-use any component between applications, so binding to an "application context" isn't really a problem for me. However, I have in the past worked on applications where I think this could be highly useful -- to isolate the configuration of the component to it's own configuration. It makes much more sense than a doc saying something like, "Don't forget to add this section, and these settings to your application's config to get this component to work."

It should be relatively easy. Configuration.ConfigurationManager would just need to look for a currentcomponent.dll.config before it looked in the exe.config (or web.config). This would isolate the settings (if needed), and still provide for a "bubble-up" if needed, or if the developer didn't need the isolation. (you could probably get most of what you're looking for by using resource files as well, I think -- and it would give you the 'change a non-code file to change the app behaviour' as well). 1/20/2008 7:32 AM | Kent Sharkey (via D'Arcy)

# re: Connection Strings, DAL's, Architecture, and Application Context

>>The reality is that there is a way to add configuration values to your assembly.<<

These are called Settings :) and yes, they can contain a connection string. But you don't want this. Really you don't.

To me, what you're suggesting here is the *opposite* of flexibility. Architecturally speaking, you should be creating components in these Class Libs that transcend any one application and can be reusable. A Data Access Layer is no exception.

Consider that you might have up to 3 databases mirrored for one application - one for testing, one for development, and another for production. How do you handle that scenario if your connection string is embedded in your assembly?

If you change DBs you need to recompile your application - that righ there is what they call a "sniff test" and should tell you right off that there's something wrong.

Let's move off of DAL for a minute - consider something like an asynchronous emailer. I have a DLL that I reuse constantly for just about every App I create. The thing that changes? The SMTP server and login.

Does this make sense?

1/21/2008 12:45 PM | Rob Conery

# re: Connection Strings, DAL's, Architecture, and Application Context

Hmm...what I should have done is maybe thrown a few other options in instead of just compare the settings and the config values. The real crux of the argument was my statement:

"I guess what I'm trying to figure out is why so many consider hard coding values a horrible thing, and yet all we're really doing with config files is creating a less-secure place to store values that we'd otherwise hard code in *and* handcuff our assemblies to our UI implementation."

Now, that's not saying that hard coding is right...I agree with all your points about why we shouldn't hard code values. But for some reason, nobody seems to see any issue with storing values that only one "tier" needs to know in a configuration file that makes those values available to *all* the application. I understand that an application on a whole has context, but I think that a component should be able to have its *own* context. I shouldn't have to add a setting to my web.config file specifying where my database is...my DAL should know where its config iinfo is and how to get it (whether that be a config file, or a registry entry, or some other way...a friend of mine has a setup using Castle Windsor to create a connection string factory that injects the required conn string at runtime).

I really like Kent's suggestion that we have some way to "bubble up" through available config files, where components would be able to keep their own contextual info without having to have that information shared between tiers. That, ultimately, would give us the greatest flexibility to ensure that data is provided only to that area of the app that needs it.

So going to your emailer component - it needs to know the SMTP server and login. In my mind, that should be something the *component* knows about, and knows where to access...but that shouldn't be something that the application context needs to share of that the applications configuration should be the place for it.

Did that clarify my point a bit?


1/21/2008 1:16 PM | D'Arcy from Winnipeg

# re: Connection Strings, DAL's, Architecture, and Application Context

That only works in scenarios where the component acts as a pass-through utility. So in the case of a mail utility, this corresponds to the real-life metaphor: my post office can't send an envelope I put in the mail unless I address it correctly...that information needs to come from me.

But let's jump back onto the DAL for a second. Data Access is bound to some form of datbase implementation, whether that be through names of stored procedures used or in the type of sql (T-SQL or Oracles variety for example) that is being used. This is information that my application, especially the UI level, shouldn't need to know; my DAL should be the owner of this information.

But the DAL is part of a larger context, the application. This is true...but it doesn't mean that the DAL shouldn't be able to act under its *own* context.

Just because the tellar works at the bank doesn't mean she should give the vault combination to the bank manager before getting money out.

D 1/21/2008 2:21 PM | D'Arcy from Winnipeg

# re: Connection Strings, DAL's, Architecture, and Application Context

And when you move your Application to your Production Box... do you reset the hard-coded connection string?

>>>Data Access is bound to some form of datbase implementation<<<

This should never be the case and you're eroding your "Loosely Coupled" argument. It's why people like ORM's so much - they develop on SQLLite and switch the adapter and move to MySQL (it's what Rails/Django do). That's modular and very cool.

>>>but it doesn't mean that the DAL shouldn't be able to act under its *own* context.<<<

The DAL has no context since it's a component of your application. The context (the environment, the user, the session) is handled entirely by the executing environment and handed to each component of the application.

>>>Just because the tellar works at the bank doesn't mean she should give the vault combination to the bank manager before getting money out.<<<

The bank is the application, not the manager. The teller is a component of said bank. If she changes jobs and tries to use her "hard-coded" vault combination at her new bank, well it wouldn't be long before she got fired ... would it?


1/21/2008 4:15 PM | Rob Conery

# re: Connection Strings, DAL's, Architecture, and Application Context

"Now, that's not saying that hard coding is right...I agree with all your points about why we shouldn't hard code values..."

That was in one of my previous comments. I'm not suggesting that we should hard code the values in the assemblies, but I am suggesting that we have options as to *where* and our components get their config information from, instead of them being forced to utilize the application's config file.

I gotta jet but I'll have more to comment here...but one thing to add quick:
Bank is Application
Tellar is UI
BankManager is DAL

Tellar goes to Bank Manager to get out money, but gives Bank Manager the vault combination because its available to all employees of the bank.

You're right that if she had a "hard coded" vault combo at her new bank she'd get fired; but if a bank manager gave the combo to everyone in the bank, he might not have a job long either.
;)

D 1/21/2008 4:45 PM | D'Arcy from Winnipeg

Post a comment