views:

499

answers:

3

We have a custom function AppSettings.GetConnectionString() which is always called to determine the connection string that should be used. How this function works is unimportant to the discussion. It suffices to say that it returns a connection string and I have to use it.

I want my LINQ to SQL DataContext to use this so I removed all connection string informatin from the dbml file and created a partial class with a default constructor like this:

public partial class SampleDataContext
{
    public SampleDataContext() : base(AppSettings.GetConnectionString()) { }
}

This works fine until I use the designer to drag and drop a table into the diagram. The act of dragging a table into the diagram will do several unwanted things:

  • A settings file will be created
  • A app.config file will be created
  • My dbml file will have the connection string embedded in it

All of this is done before I even save the file!

When I save the diagram the designer file is recreated and it will contain its own default constructor which uses the wrong connection string. Of course this means my DataContext now has two default constructors and I can't build anymore!

I can undo all of these bad things but it is annoying. I have to manually remove the connection string and the new files after each change!

Is there anyway I can stop the designer from making these changes without asking?

EDIT

The requirement to use the AppSettings.GetConnectionString() method was imposed on me rather late in the game. I used to use something very similar to what it generates for me. There are quite a few places that call the default constructor. I am aware that I dould change them all to create the data context in another way (using a different constructor, static method, factory, ect..). That kind of change would only be slightly annoying since it would only have to be done once. However, I feel, that it is sidestepping the real issue. The dbml file and configuration files would still contain an incorrect, if unused, connection string which at best could confuse other developers.

A: 

You could use something like SqlMetal to generate your own DataContext designer file, but you're right - the DataContext by default is pretty hard to crack open.

Your other option is to obtain your DataContext from a factory method, so that you can hide which constructor is actually used. Even better if you do this via an IoC framework like Castle Windsor. Then you'd be able to do things like:

var context = container.Resolve<DataContext>();
Neil Barnwell
Doesn't Visual Studio use SqlMetal to generate the designer file from the dbml file? Did you mean that I could use SqlMetal to generate the dbml from the database? While I know that it is possible there are too many things that wouldn't generate correctly this way.
drs9222
Oh, I might be confused - is SqlMetal the same as T4? I thought DataContext designer.cs files were generated with T4 templates? Point is, you could have your own custom template or code generator, but it's hard work and the factory solution I suggested is much more maintainable (and means you get the benefit of new versions/patches of L2S).
Neil Barnwell
A: 

This is a bit 'hacky' but you could add a parameter to your constructor (an unused one?), use this constructor everywhere and the default one created by the designer won't cause you any problems.

Kindness,

Dan

Daniel Elliott
There should already be a constructor that takes the connection string which I could call with a call to my method as the parameter. See my edit for why I don't want to go this way.
drs9222
+1  A: 

While in the designer for the DBML, you can right-click on any white-space, and click on Properties (not the same as right-clicking on the DBML file and clicking Properties). From there, expand the "Connection" option. Set "Application Settings" to False and clear out the "Connection String" setting. These settings are what the designer uses to create that default constructor.

From there, you can add use the default constructor you've created outside of the designer.cs file. Unfortunately, you'll have to repeat this process everything you add any new tables to the designer. It's annoying, and I feel your pain.

drovani
That is exactly what I do. I was just hoping to find a way to get rid of the pain.
drs9222
I have a feeling we've both gone through all of the same researching, only to find ourselves in the same place. It sucks, and I really wish there was an easy way to permanently disable the settings, but alas.
drovani
I do the same thing (and then I have to go remove the Connection string from the App.Config or Web.Config. ) However, one way I have found a way around this is inheriting from that DataContext Class. In my inherited class, I put the logic to dynamically get my Connection String details in the Default Constructor.
Atømix