I am working on a windows service in c#, and perhaps I might use the same methods in my web application if it works. The main service is using a sqlconnection that is used for itself, retrieved from app.config using ConfigurationManager, and it creates a few threads of different types, to run several tasks. Each of these threads has its own connection (stored in class property).
public partial class MainService : ServiceBase{
private static string SQLConnStr;
protected static SqlConnection SQLConn;
}
class OtherClass{
private sqlconnection sqlconn;
private string connstr;
}
The part that I am stuck with, is that, when I create another object type, I need that object to be able to access the DB using OtherClass' connection. This new object is created and called in OtherClass for processing later on.
Is it possible to re-use the sql connection from OtherClass?
Is it safe and secure to make the sql connection string as public static?
Is the design I am using not good?
pass it to OtherClass constructor ?
details with example:
public partial class MainService : ServiceBase{
private string SQLConnStr;
}
class OtherClass{
private string connstr;
public OtherClass(string _connstr) { this.connstr = _connstr; }
public foo() { using(var conn = new SqlConnection(connstr) { ... } }
}
Creating new SqlConnection each time is fine in .NET since there is connection pool.
You should use the respective configuration mechanism. For applications/windows services this would bee the app.config file, for web applications it would be the web.config file and for DLLs, the settings should be copied from the DLL's app.config to the application's app.config/web.config as described here many times (DLLs don't read their config files, so the settings need to go into the application's config file).
That being said: Use the settings designer in Visual Studio to simply add a new connection string setting. If necessary, add it to other projects, too.
To use the connection string from class within the same project, you can then simply use Settings.Default.MyConnectionString assuming that the setting is named MyConnectionString.
Another exception for DLLs: Some DLLs don't need their own settings, but they need to access a database. In that case you could pass the connection string or even an SqlConnection to the function that requires database access.
There is a distinction between connection*string* and the connection itself. For the connectionstring (describing where you should connect to), you can store that in a config file so youu can easily change it.
The connection itself that is used to communicate with the database must be opened and closed. When you use datareaders, you can't usually use the same connection for simultaneous commands.
It is best to open a new connection as late as possible and close it as soon as possible. Let the built-in connectionpooling do it's thing to optimize the real connections.
I like your answers, but mine is the case of bad design, after looking into it a while. So I decided to create a public static query function in the MainService:
public static void qQuery(string querystr){
using(sqlconnection conn = new sqlconnection(sqlconnstr){
.....
}
}
sqlconnstr is a private string in MainService which is initialized when the service starts.
I hope it is safe and secure way of doing it...
Related
I am writing a C# .NET 4.5-based Windows Forms application.
I'd like to set a flag (Boolean) in one of the classes (probably the main Form's class) that defines whether the app is running in Production of Debug mode. I will use this flag to control various actions of the app, including GUI-based actions as well as which connection string to use.
I don't have a problem with the GUI-based stuff because the flag is defined in the main Form's class, but I'm having a problem with the connection string. There is a separate class for DB access, which basically just defines a constant like this:
namespace MyApp
{
class DatabaseInterface
{
public static string MyConnectionString = "Data Source=server;Initial Catalog=db";
}
}
I'd like to change the connection string (really just the "server") depending on that production/debug flag. I do NOT want to put an if/then/else in every place where the connection string is used (to toggle between debug and production strings), but would like a single named connection string that can be used throughout the app. I'd also prefer to NOT have to instantiate a DatabaseInterface object (I know I could dynamically change this in the "get" definition of a public property of the DatabaseInterface class).
Is there a way to do this?
If you want to do this based on a flag and don't want the if everywhere, I'd suggest that you use a simple getter like this :
namespace MyApp
{
class DatabaseInterface
{
public static string getConnectionString()
{
return myFlag ? "Data Source=server;Initial Catalog=db" : "AnotherString";
}
}
}
Let us consider that I am having a bunch of dll [10-15] in a folder.
Now I need to search and find where and all the connection.open method used in that dll. Based on my research it can be done with reflection. So give me some ideas there by it will be helpful for me to proceed. Waiting for your valuable commands
public class GlobalInfo
{
public static string ConnectionString { get; set; }
//Method to use ti update your connectionString
public static void UpdateConnectionString(string databaseName)
{
ConnectionString = "Build your connection string";
}
}
public class MyController()
{
//Method using your connection string
public void MyMethod()
{
using(var connection = new SqlConnection(GlobalInfo.ConnectionString))
{
connection.Open();
//The rest of your code
}
}
}
And so, you need only to update your connectionString using UpdateConnectionString() method, withoud doing any reflection.
Note : In my example, I've used an SqlConnection.
Good luck.
Based on the comments and replies, what you need is IOC. Since you do not have the source code for the web application, it is going to be difficult unless original code used IOC.
What I do not understand is that if you are supposed maintain/enhance some existing code base, you need access to actual code. I guess you need to talk to your boss and get access.
You can also try and read the dll as string in your program but that will involve work which could easily be done using tools like ILSpy, Reflector etc.
I have a WinForm project that contains several UserControls. This WinForm project has a reference to an assembly (lets call it lib.dll) that is created from another project (Class Library) that exists in a different solution.
Now, several of the UserControls make calls into lib.dll that return values from the app.config file. At runtime lib.dll works fine and returns the necessary data but at design time, I am getting an exception from lib.dll because the app.config sections are NULL (the exceptions are by design).
Now I could go through each control and wrap any code that calls into lib with
if(!DesignMode) { //code }
But that is a lot of controls to go and apply that to. Is there something I can do globally that would be more elegant then testing the DesignMode property?
Edit
In response to the two comments left below: the solutions provided don't appear to work. The assembly that is causing me a problem lives in the same directory as the app.config. The general directory structure looks like this
References Folder
Configurations (Folder)
appsettings.config
app.config
lib.dll
app.config pulls in several other config files (appsettings, cnx strings, etc) which reside in the Configurations directory. In the case of my exception the value I am trying to get resides in one of these ancillary config files that is referenced by app.config.
This is an interesting question. A solution could be to create in lib.dll a static class like this one :
public static class Config
{
private static readonly _param1;
static Config()
{
_param1 = ConfigurationManager.AppSettings["Param1"] ?? "Your default value";
}
public static string Param1
{
get { return _param1; }
}
}
Then, in your code, insted of writing ConfigurationManager.AppSettings["Param1"], you will use Config.Param1. So you won't need to test the property DesignMode.
There are so many ways to do this, IMHO.
One thought that immedidately comes to mind would be to use an inheritance-based approach for the user controls in question? That way, in the base class, you can put that if (DesignMode) check in, and do the correct branching from there.
// if i were to visualizeyour lib.dll data initializer call like this:
class BaseUserControl
{
// i'm guessing that you initialize the data somehow...
void InitializeData()
{
if (!DesignMode)
{
InitializeDataLocal();
}
}
protected virtual InitializeDataLocal()
{
// whatever base behavior you want should go here.
}
}
// in the derived classes, just put the code you currently have for
// fetching the data from lib.dll here...
class UserControl : BaseUserControl
{
protected override InitializeDataLocal()
{
// fetch from lib.dll...
// optionally invoke some base behavior as well,
// if you need to...
base.InitializeDataLocal();
}
}
we use the nunit.exe application to run our (integration)test
Now i experience the problem that the connectionstring is not picked up from the app.config from the dll where the testcode is in.
That sounds logical because the nunit.exe is the starting app and not the test dll (it used to work when i started the tests from the visual studio testframework by the way), but should i put the connectionstrings in the nunit.exe.config?
I tried setting them in the testcode (works for the appsettings : ConfigurationManager.AppSettings.Set("DownloadDirectory", mDir);) like this:
ConfigurationManager.ConnectionStrings.Add(conset); (where conset is a ConnectionStringSettings object), but then i get the error that the connectionstrings section is readonly.
What should i do to use the connectionstrings in my test?
EDIT:
we use the entity framework so we can't put the connectionstring in the appsettings because it reads from the section directly, i couldn't find a way to work around this behaviour.
Using reflection, you can (in memory) change your value of the Configuration.ConnectionStrings[connectionName], which in your case you would probably do in SetUp or perhaps TestFixtureSetUp. See http://david.gardiner.net.au/2008/09/programmatically-setting.html.
// Back up the existing connection string
ConnectionStringSettings connStringSettings = ConfigurationManager.ConnectionStrings[connectionName];
string oldConnectionString = connStringSettings.ConnectionString;
// Override the IsReadOnly method on the ConnectionStringsSection.
// This is something of a hack, but will work as long as Microsoft doesn't change the
// internals of the ConfigurationElement class.
FieldInfo fi = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(connStringSettings, false);
// Set the new connection string value
connStringSettings.ConnectionString = connectionStringNeededForNUnitTest;
I realize this is not the answer you are looking for, but it is the one I applied to solve your same problem:
You can modify, in EF5 and EF4.3 at least, your DbContext implementation and add a constructor that accepts a hard coded connection string, such as this:
public partial class MyContext : DbContext
{
public MyContext() : base("name=MyContext")
{
}
// --- Here is the new thing:
public MyContext(string entityConnectionString) : base(entityConnectionString)
{
}
// --- New thing ends here
// .... the rest of the dbcontext implementation follows below
}
You would have to paste this thing in every time you regenerate your context, but IMHO it's worth the hassle. The connection string has to be entity framework formatted with your metadata and everything, but you will be able to figure it out. Just keep it somewhere so you can paste it in whenever necessary.
You can read Connection String Value from ConfigurationManager.AppSettings, yes it is readonly. You can change it in App.Config.
If you want to change some values in connection string, for ex URL, in code you can change your dataContext.URL or any properties you want with coding.
I think for unit tests it may be much easy. you may put connection string into a test class directly as hardcoded string. in simple unit tests you test limited logic scope and not care of authentically of input arguments
I'm trying to dynamically create a connection string during compile time:
private static string m_ConnectionString
{
get
{
string connectionString = #"Data Source=" + myLibrary.common.GetExeDir() + #"\Database\db.sdf;";
return connectionString;
}
}
public static string ConnectionString = m_ConnectionString;
I keep running into type initialization errors. ConnectionString ends up null at runtime. I was trying to avoid having to set the connection string for all applications that use my code library. The location of the database is different for each project that uses the library. I have code that can determine the correction string, but was wanting to run it during class initialization. Is this even possible?
I agree with Oliver's approach to discover the error, but would like to add that you could put this in a static constructor. This would achieve your requirement of "during class initialization".
public static string ConnectionString { get; private set; }
static MyClass()
{
ConnectionString = #"Data Source=" + myLibrary.common.GetExeDir() + #"\Database\db.sdf;";
}
Just set a breakpoint and step into your function and try to find out what is going wrong.
Maybe there will be some exception be thrown which you actually don't see (in some underlying code). To find these cases you should go in Visual Studio to Debug - Exceptions and check all the boxes in the list. Maybe you can find this way, why you get a null instead of a string.
That code is executed at runtime, not compile time. I think you're going down the wrong track.
Another program running as a pre build event could modify the source code of the resources.resx file, prior to compilation. You then get your connection string as a resource string.
Kind of a hack, but not the worst thing I've ever seen. My versions numbers are incremented in a similar way.