woodje
asked on
Error using readonly static classes in C# to connect to database
Hello Experts,
I am trying to setup in connection to my SQL2005 database. The error I am getting is "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)" I have tried to research this but all I am finding is an examples of the differences between static and const. I have included the part of my code that is getting errors.
Jeff
I am trying to setup in connection to my SQL2005 database. The error I am getting is "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)" I have tried to research this but all I am finding is an examples of the differences between static and const. I have included the part of my code that is getting errors.
Jeff
// Store the name of your application
private static readonly string siteName;
// Caches the connection string
private static readonly string dbConnectionString;
// Caches the data provider name
private static readonly string dbProviderName;
static void fudconfig()
{
dbConnectionString = ConfigurationManager.ConnectionStrings["fss_cao_SqlServer"].ConnectionString;
dbProviderName = ConfigurationManager.ConnectionStrings["fss_cao_SqlServer"].ConnectionString;
siteName = ConfigurationManager.AppSettings["SiteName"];
}
// Returns the connection string for the database
public static string DbConnectionString
{
get
{
return dbConnectionString;
}
}
// Returns the data provider name
public static string DbProviderName
{
get
{
return dbProviderName;
}
}
ASKER
Todd,
Sorry for the confusion. I guess I should explain more. I am using three classes. One that has the connection information, the second with all the query constructs and the third has all the data for all of the select, insert, and delete functions. I am enclosing the second class this is the constructor as you call it. I hope this helps.
Sorry for the confusion. I guess I should explain more. I am using three classes. One that has the connection information, the second with all the query constructs and the third has all the data for all of the select, insert, and delete functions. I am enclosing the second class this is the constructor as you call it. I hope this helps.
using System;
using System.Data;
using System.Data.Common;
using System.Configuration;
/// <summary>
/// Class contains generic data access functionality to be accessed from
/// the business tier
/// </summary>
public static class genericdataaccess
{
// static constructor
static genericdataaccess()
{
//
// TODO: Add constructor logic here
//
}
// execute a command and return the results as a DataTable object
public static DataTable ExecuteSelectCommand(DbCommand command)
{
// The DataTable to be returned
DataTable table;
// Execute the command making sure the connection gets closed in the end
try
{
// Open the data connection
command.Connection.Open();
// Execute the command and save the results in a DataTable
DbDataReader reader = command.ExecuteReader();
table = new DataTable();
table.Load(reader);
// Close the reader
reader.Close();
}
catch (Exception ex)
{
Utilities.LogError(ex);
throw ex;
}
finally
{
// Close the connection
command.Connection.Close();
}
return table;
}
// execute an update, delete, or insert command
// and return the number of affected rows
public static int ExecuteNonQuery(DbCommand command)
{
// The number of affected rows
int affectedRows = -1;
// Execute the command making sure the connection gets closed in the end
try
{
// Open the connection of the command
command.Connection.Open();
// Execute the command and get the number of affected rows
affectedRows = command.ExecuteNonQuery();
}
catch (Exception ex)
{
// Log eventual errors and rethrow them
Utilities.LogError(ex);
throw ex;
}
finally
{
// Close the connection
command.Connection.Close();
}
// return the number of affected rows
return affectedRows;
}
// execute a select command and return a single result as a string
public static string ExecuteScalar(DbCommand command)
{
// The value to be returned
string value = "";
// Execute the command making sure the connection gets closed in the end
try
{
// Open the connection of the command
command.Connection.Open();
// Execute the command and get the number of affected rows
value = command.ExecuteScalar().ToString();
}
catch (Exception ex)
{
// Log eventual errors and rethrow them
Utilities.LogError(ex);
throw ex;
}
finally
{
// Close the connection
command.Connection.Close();
}
// return the result
return value;
}
// creates and prepares a new DbCommand object on a new connection
public static DbCommand CreateCommand()
{
// Obtain the database provider name
string dataProviderName = Utilities.DbProviderName;
// Obtain the database connection string
string connectionString = Utilities.DbConnectionString;
// Create a new data provider factory
DbProviderFactory factory = DbProviderFactories.GetFactory(dataProviderName);
// Obtain a database specific connection object
DbConnection conn = factory.CreateConnection();
// Set the connection string
conn.ConnectionString = connectionString;
// Create a database specific command object
DbCommand comm = conn.CreateCommand();
// Set the command type to stored procedure
comm.CommandType = CommandType.StoredProcedure;
// Return the initialized command object
return comm;
}
}
Hmmm. I still don't understand. This class has no static fields and hence no assignments that could fail.
The first example shows static fields and assignments from a static method (which looks fine), but because they're readonly, that method has to be the static constructor for the class. Because you didn't show the entire class, especially the name of it, I can't tell if "fudconfig" is the constructor. That would require the first class to be called "fudconfig". Is it?
If the first class is the problem post the whole thing and tell me exactly which line you're getting the exception.
I'm guessing it's the dbConnectionString assignment below?
static void fudconfig()
{
dbConnectionString = ConfigurationManager.Conne ctionStrin gs["fss_ca o_SqlServe r"].Connec tionString ;
One final note ... why do you need this field to be readonly? If it's private to the class, code outside the class can't access it anyway.
The first example shows static fields and assignments from a static method (which looks fine), but because they're readonly, that method has to be the static constructor for the class. Because you didn't show the entire class, especially the name of it, I can't tell if "fudconfig" is the constructor. That would require the first class to be called "fudconfig". Is it?
If the first class is the problem post the whole thing and tell me exactly which line you're getting the exception.
I'm guessing it's the dbConnectionString assignment below?
static void fudconfig()
{
dbConnectionString = ConfigurationManager.Conne
One final note ... why do you need this field to be readonly? If it's private to the class, code outside the class can't access it anyway.
ASKER
Thanks Todd,
Here is the full class.
Here is the full class.
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Net.Mail;
/// <summary>
/// Class contains miscellaneous functionality
/// </summary>
///
public static class Utilities
{
// Store the name of your application
private static readonly string siteName;
// Caches the connection string
private static readonly string dbConnectionString;
// Caches the data provider name
private static readonly string dbProviderName;
// Initialize various properties in the constructor
static void fudconfig()
{
dbConnectionString = ConfigurationManager.ConnectionStrings["fss_cao_SqlServer"].ConnectionString;
dbProviderName = ConfigurationManager.ConnectionStrings["fss_cao_SqlServer"].ConnectionString;
siteName = ConfigurationManager.AppSettings["SiteName"];
}
// Returns the connection string for the database
public static string DbConnectionString
{
get
{
return dbConnectionString;
}
}
// Returns the data provider name
public static string DbProviderName
{
get
{
return dbProviderName;
}
}
// Send error log emails?
public static bool EnableErrorLogEmail
{
get
{
return bool.Parse(ConfigurationManager.AppSettings["EnableErrorLogEmail"]);
}
}
// Returns the email address where to send error reports
public static string ErrorLogEmail
{
get
{
return ConfigurationManager.AppSettings["ErrorLogEmail"];
}
}
// Returns the length of product descriptions in products lists
public static string SiteName
{
get
{
return siteName;
}
}
// Generic method for sending emails
public static void SendMail(string from, string to, string subject, string body)
{
// Configure mail client (may need additional
// code for authenticated SMTP servers)
SmtpClient mailClient = new SmtpClient(ConfigurationManager.AppSettings["SMTP"],25);
// Create the mail message
MailMessage mailMessage = new MailMessage(from, to, subject, body);
/*
// For SMTP servers that require authentication
message.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", 1);
message.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", "SmtpHostUserName");
message.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", "SmtpHostPassword");
*/
// Send mail
mailClient.Send(mailMessage);
}
// Send error log mail
public static void LogError(Exception ex)
{
// get the current date and time
string dateTime = DateTime.Now.ToLongDateString() + ", at "
+ DateTime.Now.ToShortTimeString();
// stores the error message
string errorMessage = "Exception generated on " + dateTime;
// obtain the page that generated the error
System.Web.HttpContext context = System.Web.HttpContext.Current;
errorMessage += "\n\n Page location: " + context.Request.RawUrl;
// build the error message
errorMessage += "\n\n Message: " + ex.Message;
errorMessage += "\n\n Source: " + ex.Source;
errorMessage += "\n\n Method: " + ex.TargetSite;
errorMessage += "\n\n Stack Trace: \n\n" + ex.StackTrace;
// send error email in case the option is activated in Web.Config
if (Utilities.EnableErrorLogEmail)
{
string from = "noreply@verizonwireless.com";
string to = Utilities.ErrorLogEmail;
string subject = Utilities.SiteName + " error report";
string body = errorMessage;
SendMail(from, to, subject, body);
}
}
// Configures what button to be clicked when the uses presses Enter in a
// textbox. The text box doesn't have to be a TextBox control, but it must
// be derived from either HtmlControl or WebControl, and the HTML control it
// generates should accept an 'onkeydown' attribute. The HTML generated by
// the button must support the 'Click' event
public static void TieButton(Page page, Control TextBoxToTie, Control ButtonToTie)
{
// Init jscript
string jsString = "";
// Check button type and get required jscript
if (ButtonToTie is LinkButton)
{
jsString = "if ((event.which && event.which == 13) || (event.keyCode && event.keyCode == 13)) {"
+ page.ClientScript.GetPostBackEventReference(ButtonToTie, "").Replace(":", "$") + ";return false;} else return true;";
}
else if (ButtonToTie is ImageButton)
{
jsString = "if ((event.which && event.which == 13) || (event.keyCode && event.keyCode == 13)) {"
+ page.ClientScript.GetPostBackEventReference(ButtonToTie, "").Replace(":", "$") + ";return false;} else return true;";
}
else
{
jsString = "if ((event.which && event.which == 13) || (event.keyCode && event.keyCode == 13)) {document."
+ "forms[0].elements['" + ButtonToTie.UniqueID.Replace(":", "_") + "'].click();return false;} else return true; ";
}
// Attach jscript to the onkeydown attribute - we have to cater for HtmlControl or WebControl
if (TextBoxToTie is HtmlControl)
{
((HtmlControl)TextBoxToTie).Attributes.Add("onkeydown", jsString);
}
else if (TextBoxToTie is WebControl)
{
((WebControl)TextBoxToTie).Attributes.Add("onkeydown", jsString);
}
}
}
ASKER
No it is called Utilities.
ASKER
Todd,
You are correct that line of code is where I am getting the error. The "dbConnectionString" is what is highlighted. To the question of why is it static. That is the way the book I was using had these classes built. I don't understand it all 100% yet. So goes the learning.
You are correct that line of code is where I am getting the error. The "dbConnectionString" is what is highlighted. To the question of why is it static. That is the way the book I was using had these classes built. I don't understand it all 100% yet. So goes the learning.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I'm not asking why it's static, but rather readonly. These are different concepts. Keep reading about this stuff and it will start to make sense.
readonly - once the field is assigned a value (constructor or inline initializer) it can't be changed. Personally, I don't use this very often at all.
static, it's created ONCE for the application, regardless of how many instances of the class you create. If you only have a single instance of this class .. you can just NOT MESS with static and be happy as a lark.
readonly - once the field is assigned a value (constructor or inline initializer) it can't be changed. Personally, I don't use this very often at all.
static, it's created ONCE for the application, regardless of how many instances of the class you create. If you only have a single instance of this class .. you can just NOT MESS with static and be happy as a lark.
ASKER
That worked perfectly. I was trying to rename to the application functions and injected this problem. Thanks for the lesson I will keep learning.
That looks right, but if it's not the constructor, then it won't work.
A static constructor is just like a non-static, but with the modifier. In fact, you can have both at the same time.