Is it possible to dynamically set a static string during *class* Initialization? - c#

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.

Related

is public static sql connection secure

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...

Dynamic connection strings based on Production/Debug flag

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";
}
}
}

Retrieving sqlconnection.open class used in dll

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.

The type initializer for 'MyClass' threw an exception

The following is my Windows service code. When I am debugging the code, I am getting the error/ exception:
The type initializer for 'CSMessageUtility.CSDetails' threw an exception.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.IO;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
using CSMessageUtility;
namespace CS_Data_Trasmmiting_Service
{
public partial class svcCSWinServ : ServiceBase
{
//private string sLogFormat;
//private string sErrorTime;
private Thread new_thread;
Logger logObject = new Logger();
private bool isenable = true;
public svcCSWinServ()
{
InitializeComponent();
logObject.append("Initialize Service " + DateTime.Now.ToString(), 70);
CheckForAlarms();
}
protected override void OnStart(string[] args)
{
try
{
new_thread = new Thread(new ThreadStart(CheckForAlarms));
new_thread.Start();
}
catch
{
}
logObject.append("Service Started successfully " + DateTime.Now.ToString(), 70);
}
protected override void OnStop()
{
try
{
isenable = false;
new_thread.Abort();
}
catch
{
}
logObject.append("Service Stopped successfully " + DateTime.Now.ToString(), 70);
}
void CheckForAlarms()
{
try
{
while (true)
{
//if((DateTime.Now.ToString("HH:mm") == "18:00"))
//{
logObject.append("Start Sending Data " +DateTime.Now.ToString(), 70);
try
{
//SendAllInfo();
string str = CSMessageUtility.CSDetails.createDHSMessageFormat();
Thread.Sleep(2000);
string str1 = CSMessageUtility.CSDetails.createEALMessageFormat();
Thread.Sleep(2000);
string str2 = CSMessageUtility.CSDetails.createProductStatusMessageForamt();
Thread.Sleep(2000);
string str3 = CSMessageUtility.CSDetails.createEODMessageFormat();
Thread.Sleep(2000);
string str4 = CSDetails.createProductReceiptEntryatBOSMessageFormat();
Thread.Sleep(2000);
string str5 = CSMessageUtility.CSDetails.createProductSaleMessageFormat();
Thread.Sleep(2000);
string str6 = CSMessageUtility.CSDetails.createTotalizerExceptionMessageFormat();
Thread.Sleep(2000);
//CSMessageUtility.CSDetails.createDailyCOtransferMessageFormat();
//Thread.Sleep(2000);
}
catch (Exception ee)
{
logObject.append(ee.Message, 70);
}
logObject.append("Finished Sending Data " +DateTime.Now.ToString(), 70);
Thread.Sleep(3000);
//}
//Thread.Sleep(20000);
}
}
catch (Exception ex)
{
logObject.append("Thread Exception: "+ ex.Message + " "+ DateTime.Now.ToString(), 70);
try
{
new_thread.Abort();
}
catch (Exception ex1)
{
logObject.append("Thread Exception: " +ex1.Message + " " + DateTime.Now.ToString(), 70);
}
if (isenable == true)
{
new_thread = new Thread(new ThreadStart(CheckForAlarms));
new_thread.Start();
}
}
}
}
}
Check the InnerException property of the TypeInitializationException; it is likely to contain information about the underlying problem, and exactly where it occurred.
This problem can be caused if a class tries to get value of a key in web.config or app.config which is not present there.
e.g.
The class has a static variable
private static string ClientID = System.Configuration.ConfigurationSettings.AppSettings["GoogleCalendarApplicationClientID"].ToString();
But the web.config doesn't contain the GoogleCalendarApplicationClientID key
The error will be thrown on any static function call or any class instance creation
The type initializer for 'CSMessageUtility.CSDetails' threw an exception. means that the static constructor on that class threw an Exception - so you need to look either in the static constructor of the CSDetails class, or in the initialisation of any static members of that class.
I ran into the same problem, when I was using a static methods in a Util class, just like you had used CSMessageUtility.CSDetails.
The problem was that during the static initialization of the class (using the static constructor), the framework also initialize the the static variables (fields) in the class. I had a static variable that attempts to read values from app.config, and app.config was missing the respective settings, thus resulting in an un-handled exception. This resulted in getting the
"Object reference not set to an instance of an object."
as the inner exception.
One other thing to check when these initialize errors are thrown would be to check if the target .NET version is installed on the server. You can right click the project and see what .NET version the application is targeting.
Dictionary keys should be unique !
In my case, I was using a Dictionary, and I found two items in it have accidentally the same key.
Dictionary<string, string> myDictionary = new Dictionary<string, string>() {
{"KEY1", "V1"},
{"KEY1", "V2" },
{"KEY3", "V3"},
};
This can happen if you have a dependency property that is registered to the wrong owner type (ownerType argument).
Notice SomeOtherControl should have been YourControl.
public partial class YourControl
{
public bool Enabled
{
get { return (bool)GetValue(EnabledProperty); }
set { SetValue(EnabledProperty, value); }
}
public static readonly DependencyProperty EnabledProperty =
DependencyProperty.Register(nameof(Enabled), typeof(bool), typeof(SomeOtherControl), new PropertyMetadata(false));
}
I've had the same problem caused by having two of the same configuration properties (which matches the app.config):
[ConfigurationProperty("TransferTimeValidity")]
Another scenario that might cause this is when you have a piece of your code that calls:
string sParam = **ConfigurationManager.AppSettings["SOME_PARAM"].ToString();
Keep in mind that you have to use the OWSTIMER.EXE.CONFIG file for configuration file settings. I had an App.config file that I was trying to read and I was getting this error because on instantiation of my job instance, I had a line in my code that was referring to Connfiguration.AppSettings & Configuration.ConnectionStrings. Just make sure that you go the path:
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN
and place your configuration settings in the OWSTIMER.EXE.CONFIG file.
If for whatever reason the power goes or the Visual Studio IDE crashes it can cause this problem inside your bin/debug bin/release...
Just delete the content and recompile (from personal experience when my toe hit the reset button!)
I had a different but still related configuration.
Could be a custom configuration section that hasn't been declared in configSections.
Just declare the section and the error should resolve itself.
I encountered this issue due to mismatch between the runtime versions of the assemblies. Please verify the runtime versions of the main assembly (calling application) and the referred assembly
As the Error says the initialization of the Type/Class failed. This usually occurs when there is some exception in the constructor of the class. Most common reason is you assign some value in the constructor reading from a config file and the config file is missing those values.
Noteworthy: I had multiple projects in my solution and I forgot to add the references/Nuget libraries. When I ran a method in the static class, which used the given libraries, it threw the exception mentioned.
In my case I had this failing on Logger.Create inside a class library that was being used by my main (console) app. The problem was I had forgotten to add a reference to NLog.dll in my console app. Adding the reference with the correct .NET Framework library version fixed the problem.
Had a case like this in a WPF project. My issue was on a line that went like this:
DataTable myTable = FillTable(strMySqlQuery);
Where FillTable() returned a DataTable based on a SQL query string. If I did the "copy exception to clipboard" option, I think it was, and pasted into Notepad, I could see the message. For me, it was The input is not a valid Base-64 string as it contains a non-base 64 character.
My actual problem wasn't that the query string had something that shouldn't be there, like I was thinking, because string strMySqlQuery = "SELECT * FROM My_Table" was my string and thought it could be the * or _, but the actual problem was in FillTable(), where I had a call to another function, GetConnection() that returned an OracleConnection object, in order to open it and retrieve and return the DataTable. Inside GetConnection() I was getting the app.config parameters for my connection string, and I had one of them misnamed, so it was setting a null value for the service account's password and not making the DB connection. So it's not always where the error is exactly correct for all circumstances. Best to dive into the function where the error is and debug step-by-step and ensure all values are getting filled with what you expect.
I too faced this error in two situation
While performing redirection from BAL layer to DAL layer I faced this exception. Inner exception says that "Object Reference error".
Web.Config file key does not match.
Hope this useful to solve your problem.
Similar to what Muhammad Iqbal stated.. I was in a VB.NET (may also be C#) project where I did remove a key-value pair from the App.config which was referenced by a variable global to the Sub Main() of Module Main. Therefore, the exception (and break) occurs in Module Main before the Sub Main(). If only I had a break-point on the Dim, but we don't usually break on global variables. Perhaps a good reason not to declare globals referencing App.config? In other words, this...
An unhandled exception of type 'System.TypeInitializationException' occurred in Unknown Module.
The type initializer for 'Namespace.Main' threw an exception.
Is caused by...
App.config
<connectionStrings>
<!--<add name="ConnectionString1" connectionString="..." />-->
Main module
Module Main
Dim cnnString As String = ConfigurationManager.ConnectionStrings("ConnectionString1") '<-- BREAK HERE (EXCEPTION)
Sub Main()
// main code
End Main
End Module
In my case, I had a helper class that was static. In that class was a method to initialize a SqlCommand dependent on variables. As this was being called in several places I moved it to the helper class and called as needed, so this method was also static. Now I had a global property that was the connection string in Global.asax pointing to the connection string in web.config. Intermittently I would get "The type initializer for 'Helper' threw an exception". If I moved the method from the Helper class to the class where it was being called from all was good. The inner exception complained of the object being null (Helper class). What I did was add Using Helper to Global.asax and even though it was not being used by Global.asax this solved the problem.
My Answer is also related to Config section. If you assign values from Config file at static class of C# or Module.VB of VB, you will get this error at run time.
add key="LogPath" value="~/Error_Log/"
Using Forward slash in Web.Config also leads to this error on Run time. I just resolved this issue by putting BackSlash
add key="LogPath" value="~\Error_Log\"
I wrapped my line that was crashing in a try-catch block, printed out the exception, and breaked immediately after it was printed. The exception information shown had a stack trace which pointed me to the file and line of code causing the fault to occur.
System.TypeInitializationException: The type initializer for 'Blah.blah.blah' threw an exception.
---> System.NullReferenceException: Object reference not set to an instance of an object.
at Some.Faulty.Software..cctor() in C:\Projects\My.Faulty.File.cs:line 56
--- End of inner exception stack trace ---
at Blah.blah.blah(Blah.blah.blah)
at TestApplication.Program.Main(String[] args)
in C:\Projects\Blah.blah.blah\Program.cs:line 29 Exception caught.
Somehow exiting Visual Studio and re-opening it solved this for me.

Using the connectionstring in an nunit test

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

Categories