[Webinar] Streamline your web hosting managementRegister Today

x
?
Solved

Error using readonly static classes in C# to connect to database

Posted on 2010-03-29
9
Medium Priority
?
372 Views
Last Modified: 2012-05-09
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
// 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;
        }
    }

Open in new window

0
Comment
Question by:woodje
  • 5
  • 4
9 Comments
 
LVL 16

Expert Comment

by:ToddBeaulieu
ID: 29014671
Is "static void fudconfig()" your static constructor? Hard to tell from the snippet.

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

Author Comment

by:woodje
ID: 29015870
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.


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

Open in new window

0
 
LVL 16

Expert Comment

by:ToddBeaulieu
ID: 29016493
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.ConnectionStrings["fss_cao_SqlServer"].ConnectionString;

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.
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 

Author Comment

by:woodje
ID: 29017006
Thanks Todd,

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

Open in new window

0
 

Author Comment

by:woodje
ID: 29017047
No it is called Utilities.
0
 

Author Comment

by:woodje
ID: 29017308
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.
0
 
LVL 16

Accepted Solution

by:
ToddBeaulieu earned 2000 total points
ID: 29017568
Ok. That explains it. As the message indicated, you can only assign to readonly fields via a static constructor. You're not doing that.

In the code below I simply renamed "fudconfig" to "Utilities". This made it the sstatic constructor for the class.

Now, this doesn't necessarily mean it's the final answer. I didn't look to see where you're calling "fudconfig" from to init these fields. If setting them in the constructor is adequate, then you're all set after removing any reference to "fudconfig".

Again, be sure to always think "am I going about this the right way", when stuck on solutions like this. Eliminating the readonly attribute is most likely entirely adequate for you.
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 Utilities()
    {        
        dbConnectionString = ConfigurationManager.ConnectionStrings["fss_cao_SqlServer"].ConnectionString;
        dbProviderName =  ConfigurationManager.ConnectionStrings["fss_cao_SqlServer"].ConnectionString;
        siteName = ConfigurationManager.AppSettings["SiteName"];
    }

Open in new window

0
 
LVL 16

Expert Comment

by:ToddBeaulieu
ID: 29017772
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.
0
 

Author Closing Comment

by:woodje
ID: 31708549
That worked perfectly. I was trying to rename to the application functions and injected this problem. Thanks for the lesson I will keep learning.
0

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

User art_snob (http://www.experts-exchange.com/M_6114203.html) encountered strange behavior of Android Web browser on his Mobile Web site. It took a while to find the true cause. It happens so, that the Android Web browser (at least up to OS ver. 2.…
The article shows the basic steps of integrating an HTML theme template into an ASP.NET MVC project
Kernel Data Recovery is a renowned Data Recovery solution provider which offers wide range of softwares for both enterprise and home users with its cost-effective solutions. Let's have a quick overview of the journey and data recovery tools range he…
Enter Foreign and Special Characters Enter characters you can't find on a keyboard using its ASCII code ... and learn how to make a handy reference for yourself using Excel ~ Use these codes in any Windows application! ... whether it is a Micr…
Suggested Courses

591 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question