.NETGURU
Problem with Singleton object instance
Messages   Related Types
This message was discovered on ASPFriends.com 'ngfx-patterns' list.
Responses highlighted in red are from those people who are likely to be able to contribute good, authoratitive information to this discussion. They include Microsoft employees, MVP's and others who IMHO contribute well to these kinds of discussions.

Leary, William P.
-- Copied from [aspngcs] to [ngfx-patterns] by Charles D. Carroll <Click here to reveal e-mail address> --Greetings all,I am working on a report generator project, and am trying to make an objectusing the Singleton design pattern. (Which I have never done before.) It'spurpose is to return DataSets as a report is being recursively built. i.e.looping through a DataSet    loop through another DataSet, which was retrieved from a call to mySingleton passing a value from the current row        ...I purposely want to keep the connection open, in case you were wondering, asclosing and re-opening it drags performance way down. I have tested this, aswell as putting the entire report DataSet in memory, and using DataViewsthat I adjust per row, but that is still not as good as making very targetedqueries, since the data source is very large, and each time through theloop, I refine it further. Imagine building a report displaying:widget category    widgets        widgets at locationJust giving a background. Here's the code causing grief:        public class ReportData        {            SqlConnection m_cnn = null;            SqlCommand m_cmd = null;            SqlDataAdapter m_adp = null;                        static ReportData _instance = null;            private ReportData()            {                ;            }            public static ReportData Instance()            {                if (_instance == null)                {                    _instance = new ReportData();                }                return _instance;            }            public void OpenConnection(string DSN)            {                // If the connection is already open, throwan error.                if (m_cnn != null)                    throw new Exception("Connection isalready open!");                m_cnn = new SqlConnection(DSN);                // Create the command object.                m_cmd = new SqlCommand();                m_cmd.Connection = m_cnn;                m_cmd.CommandType = CommandType.Text;                // Create the adapter object.                m_adp = new SqlDataAdapter();                m_adp.SelectCommand = m_cmd;                // Open the connection                m_cnn.Open();            }            public void CloseConnection()            {                // Cleanup the command.                m_cmd.Connection = null;                m_cmd.Dispose();                // Cleanup the data adapter.                m_adp.SelectCommand = null;                m_adp.Dispose();                                // Clean up the connection.                m_cnn.Close();                m_cnn.Dispose();            }            public DataSet GetDataSet(string SQL)            {                DataSet ds = new DataSet();                m_cmd.CommandText = SQL;                m_adp.Fill(ds);                return ds;            }        }Each time I use this object, I can only the .aspx page it is in once. Then,when I refresh the page, I get the error I'm throwing when I hit theOpenConnection call. Obviously, something is sticking around, and I don'tknow why. I don't think it's connection pooling per se, because if that wasthe case, why doesn't the first call fail. Here is sample code showing howto make it fail: (Just replace the DSN with something valid...I'm using akey in the web.config file.)using System;using System.Collections;using System.ComponentModel;using System.Configuration;using System.Data;using System.Data.SqlClient;using System.Drawing;using System.Web;using System.Web.SessionState;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;namespace CCInfo{    /// <summary>    /// Summary description for DemoFail.    /// </summary>    public class DemoFail : System.Web.UI.Page    {        private void Page_Load(object sender, System.EventArgs e)        {            // Create the object.            ReportData rpt = ReportData.Instance();            // Open and close. I would think resources are freedhere.    rpt.OpenConnection(ConfigurationSettings.AppSettings["DSN"]);            rpt.CloseConnection();            // Clean up my object instance.            rpt = null;        }        public class ReportData        {            SqlConnection m_cnn = null;            SqlCommand m_cmd = null;            SqlDataAdapter m_adp = null;                        static ReportData _instance = null;            private ReportData()            {                ;            }            public static ReportData Instance()            {                if (_instance == null)                {                    _instance = new ReportData();                }                return _instance;            }            public void OpenConnection(string DSN)            {                // If the connection is already open, throwan error.                if (m_cnn != null)                    throw new Exception("Connection isalready open!");                m_cnn = new SqlConnection(DSN);                // Create the command object.                m_cmd = new SqlCommand();                m_cmd.Connection = m_cnn;                m_cmd.CommandType = CommandType.Text;                // Create the adapter object.                m_adp = new SqlDataAdapter();                m_adp.SelectCommand = m_cmd;                // Open the connection                m_cnn.Open();            }            public void CloseConnection()            {                // Cleanup the command.                m_cmd.Connection = null;                m_cmd.Dispose();                // Cleanup the data adapter.                m_adp.SelectCommand = null;                m_adp.Dispose();                                // Clean up the connection.                m_cnn.Close();                m_cnn.Dispose();            }            public DataSet GetDataSet(string SQL)            {                DataSet ds = new DataSet();                m_cmd.CommandText = SQL;                m_adp.Fill(ds);                return ds;            }        }        #region Web Form Designer generated code        override protected void OnInit(EventArgs e)        {            //            // CODEGEN: This call is required by the ASP.NET WebForm Designer.            //            InitializeComponent();            base.OnInit(e);        }                /// <summary>        /// Required method for Designer support - do not modify        /// the contents of this method with the code editor.        /// </summary>        private void InitializeComponent()        {             this.Load += newSystem.EventHandler(this.Page_Load);        }        #endregion    }}So, I can run the above just once. The second time (by hitting refresh) iterrors when OpenConnection is called, and throws the error I'm checking for.Is this a garbage collection issue? Am I missing something in how I'mcleaning up? Anyone encounter anything like this? Appreciate any and allhelp.Cheers,William LearySr. Web Applications DeveloperClear Channel Information Technology
Reply to this message...
 
    
Jim Arnold
You're testing for null, but not setting your connection to null, so the
test always fails.

This will fix it:

public void CloseConnection() {
    //...
    m_cnn.Close();
    m_cnn.Dispose();
    m_cnn = null;
}

Jim

[Original message clipped]

Reply to this message...
 
    
Leary, William P.
THANK YOU!!!!!!!!!!!!!!!!!!!!!!!!!! Man, I can't believe I didn't try that.
You're right. I just tested it, and it works. I (obviously wrongly) assumed
that when I called Dispose(), that would garbage collect the connection when
the page is done executing, and that the next time the page is hit, it would
be gone and of course be null. Thanks. I've only been doing C# for about 4
weeks now, so I have a lot to learn. Thanks again.

-----Original Message-----
From: Jim Arnold [mailto:Click here to reveal e-mail address]
Sent: Friday, January 25, 2002 11:17 AM
To: ngfx-patterns
Subject: [ngfx-patterns] RE: Problem with Singleton object instance

You're testing for null, but not setting your connection to null, so the
test always fails.

This will fix it:

public void CloseConnection() {
    //...
    m_cnn.Close();
    m_cnn.Dispose();
    m_cnn = null;
}

Jim

[Original message clipped]

| [ngfx-patterns] member Click here to reveal e-mail address = YOUR ID
| http://www.aspfriends.com/aspfriends/ngfx-patterns.asp = JOIN/QUIT

Reply to this message...
 
    
Jim Arnold
No problem. Calling Dispose() on a connection just closes it and returns it
to the pool. The reference still exists because it's a member of the
singleton. You'd be better off just closing the connection (then checking
for ConnectionState.Closed when you call Open() again) rather than nulling
it, because it's relatively more expensive to build a new object every time.

Jim

[Original message clipped]

Reply to this message...
 
    
Francesco Sanfilippo
So, to clarify, Connection.Dispose() calls Connection.Close() internally?
So one does not need to do this:

Connection.Close();
Connection.Dispose();

Francesco

[Original message clipped]

_________________________________________________________________
Send and receive Hotmail on your mobile device: http://mobile.msn.com

Reply to this message...
 
    
Ryan Trudelle-Schwarz (VIP)
Yes, that's correct.

-----Original Message-----
From: Francesco Sanfilippo [mailto:Click here to reveal e-mail address]

So, to clarify, Connection.Dispose() calls Connection.Close()
internally?
So one does not need to do this:

Connection.Close();
Connection.Dispose();

Francesco

Reply to this message...
 
    
Leary, William P.
Warning to all...I just found observed something when using a Singleton with
an ASP.Net page: It is a Singleton across ALL ASP.Net pages. I thought that
it would only exist in the context of that one executing page, and that if
any object's in that page tried to create more than one instance of my
object, they would get the one inside the page. But, it clearly is not
so,...there is one instance across the board. If I hit that page with
another browser, while the first is executing, I get the value that the
first one still has. I think I need to do more research about how ASP.Net
pages work. I suspect this has something to do with 'app domains', or at
least, that's something fuzzy in my memory...Anyway, just a warning. I've
thus scrapped the Singleton and relying again on connection pooling.

-----Original Message-----
From: Ryan Trudelle-Schwarz [mailto:Click here to reveal e-mail address]
Sent: Saturday, January 26, 2002 1:51 PM
To: ngfx-patterns
Subject: [ngfx-patterns] RE: Problem with Singleton object instance

Yes, that's correct.

-----Original Message-----
From: Francesco Sanfilippo [mailto:Click here to reveal e-mail address]

So, to clarify, Connection.Dispose() calls Connection.Close()
internally?
So one does not need to do this:

Connection.Close();
Connection.Dispose();

Francesco

| [ngfx-patterns] member Click here to reveal e-mail address = YOUR ID
| http://www.aspfriends.com/aspfriends/ngfx-patterns.asp = JOIN/QUIT

Reply to this message...
 
    
Jim Arnold
Static member variables (of which a Singleton is usually one) exist across
applications so yes, all objects in an ASP.Net application boundary will
share the same instance. If you want one instance per page, it's not a
Singleton, it's just an object. What are you trying to achieve?

Jim

[Original message clipped]

Reply to this message...
 
    
Trevor
Hmmm... to me thats the idea of singleton. I don't think its a problem at all.

ie. Say you have a site that supports French and English languages and you
store 1000 corresponding french/english labels in a database. One may
store them in an array instead of hitting the database each page load.

Then... you create one instance of this French/English array in memory
within a singleton object. Lets say the size of this object is one
meg. Now, if we have 100 concurrent page hits... the way you want the
object to work would mean 100 1 meg objects in memory. Why not just have 1
that all pages share?

I am not a patterns master. but i'm pretty sure thats the purpose of
singleton.

Anyone else?

-Trevor

At 10:26 AM 1/28/2002 -0600, you wrote:
[Original message clipped]

Reply to this message...
 
    
Leary, William P.
I thought, incorrectly, that the page was an "application boundary". I
wanted to prevent a specific object from being recreated more than once
within that page. The Singleton concept works just fine, in theory, for
that. I am working on a report writer, and wanted to issue multiple calls to
a single data object. I wanted to ensure that I didn't accidentally create
that object more than once, and if I did, I would just use the one already
existing. I tested it and verified that avoiding the calls to create a new
SQLConnection object repeatedly did save time. (I want to reuse the
connection, since I'm not caching the data...already tried it that way, and
because the possible records returned are in the tens of thousands, sending
numerous highly targeted parameterized queries is much more efficient than
pulling all over and navigating them via DataViews) I have not delved into
the guts of the .Net Framework yet...just C# and ASP.Net, so that is why I'm
unclear on many of these issues regarding app boundaries and whatnot.

-----Original Message-----
From: Jim Arnold [mailto:Click here to reveal e-mail address]
Sent: Monday, January 28, 2002 12:46 PM
To: ngfx-patterns
Subject: [ngfx-patterns] RE: Problem with Singleton object instance

Static member variables (of which a Singleton is usually one) exist across
applications so yes, all objects in an ASP.Net application boundary will
share the same instance. If you want one instance per page, it's not a
Singleton, it's just an object. What are you trying to achieve?

Jim

[Original message clipped]

| [ngfx-patterns] member Click here to reveal e-mail address = YOUR ID
| http://www.aspfriends.com/aspfriends/ngfx-patterns.asp = JOIN/QUIT

Reply to this message...
 
    
Leary, William P.
For the record, I think the correct term I should be using is "application
domain", not "application boundary".

-----Original Message-----
From: Leary, William P. [mailto:Click here to reveal e-mail address]
Sent: Monday, January 28, 2002 2:58 PM
To: ngfx-patterns
Subject: [ngfx-patterns] RE: Problem with Singleton object instance

I thought, incorrectly, that the page was an "application boundary". I
wanted to prevent a specific object from being recreated more than once
within that page. The Singleton concept works just fine, in theory, for
that. I am working on a report writer, and wanted to issue multiple calls to
a single data object. I wanted to ensure that I didn't accidentally create
that object more than once, and if I did, I would just use the one already
existing. I tested it and verified that avoiding the calls to create a new
SQLConnection object repeatedly did save time. (I want to reuse the
connection, since I'm not caching the data...already tried it that way, and
because the possible records returned are in the tens of thousands, sending
numerous highly targeted parameterized queries is much more efficient than
pulling all over and navigating them via DataViews) I have not delved into
the guts of the .Net Framework yet...just C# and ASP.Net, so that is why I'm
unclear on many of these issues regarding app boundaries and whatnot.

-----Original Message-----
From: Jim Arnold [mailto:Click here to reveal e-mail address]
Sent: Monday, January 28, 2002 12:46 PM
To: ngfx-patterns
Subject: [ngfx-patterns] RE: Problem with Singleton object instance

Static member variables (of which a Singleton is usually one) exist across
applications so yes, all objects in an ASP.Net application boundary will
share the same instance. If you want one instance per page, it's not a
Singleton, it's just an object. What are you trying to achieve?

Jim

[Original message clipped]

| [ngfx-patterns] member Click here to reveal e-mail address = YOUR ID
| http://www.aspfriends.com/aspfriends/ngfx-patterns.asp = JOIN/QUIT

| [ngfx-patterns] member Click here to reveal e-mail address = YOUR ID
| http://www.aspfriends.com/aspfriends/ngfx-patterns.asp = JOIN/QUIT

Reply to this message...
 
    
Andy Smith (VIP)
The singleton pattern will still work for you... you just have to reduce
the scope of the singleton.
create a private connection object in your page, then create a
getConnection function in your page.
SqlConnection getConnection() {
if ( myConnection == null ) {
createNewConnection();
}
return myConnection;
}

it's the same concept of a standard singleton, it's just reduced in
scope to the lifetime of a page.

__
Andy Smith
Chief Code Monkey

>>> Click here to reveal e-mail address 01/28/02 01:58PM >>>
I thought, incorrectly, that the page was an "application boundary". I
wanted to prevent a specific object from being recreated more than
once
within that page. The Singleton concept works just fine, in theory,
for
that. I am working on a report writer, and wanted to issue multiple
calls to
a single data object. I wanted to ensure that I didn't accidentally
create
that object more than once, and if I did, I would just use the one
already
existing. I tested it and verified that avoiding the calls to create a
new
SQLConnection object repeatedly did save time. (I want to reuse the
connection, since I'm not caching the data...already tried it that way,
and
because the possible records returned are in the tens of thousands,
sending
numerous highly targeted parameterized queries is much more efficient
than
pulling all over and navigating them via DataViews) I have not delved
into
the guts of the .Net Framework yet...just C# and ASP.Net, so that is
why I'm
unclear on many of these issues regarding app boundaries and whatnot.

-----Original Message-----
From: Jim Arnold [mailto:Click here to reveal e-mail address]
Sent: Monday, January 28, 2002 12:46 PM
To: ngfx-patterns
Subject: [ngfx-patterns] RE: Problem with Singleton object instance

Static member variables (of which a Singleton is usually one) exist
across
applications so yes, all objects in an ASP.Net application boundary
will
share the same instance. If you want one instance per page, it's not
a
Singleton, it's just an object. What are you trying to achieve?

Jim

[Original message clipped]

| [ngfx-patterns] member Click here to reveal e-mail address = YOUR ID
| http://www.aspfriends.com/aspfriends/ngfx-patterns.asp = JOIN/QUIT

| [ngfx-patterns] member Click here to reveal e-mail address = YOUR ID
| http://www.aspfriends.com/aspfriends/ngfx-patterns.asp = JOIN/QUIT

Reply to this message...
 
    
Leary, William P.
Hmmm...hadn't thought of that. Good idea!

-----Original Message-----
From: Andy Smith [mailto:Click here to reveal e-mail address]
Sent: Monday, January 28, 2002 3:02 PM
To: ngfx-patterns
Subject: [ngfx-patterns] RE: Problem with Singleton object instance

The singleton pattern will still work for you... you just have to reduce
the scope of the singleton.
create a private connection object in your page, then create a
getConnection function in your page.
SqlConnection getConnection() {
if ( myConnection == null ) {
createNewConnection();
}
return myConnection;
}

it's the same concept of a standard singleton, it's just reduced in
scope to the lifetime of a page.

__
Andy Smith
Chief Code Monkey

>>> Click here to reveal e-mail address 01/28/02 01:58PM >>>
I thought, incorrectly, that the page was an "application boundary". I
wanted to prevent a specific object from being recreated more than
once
within that page. The Singleton concept works just fine, in theory,
for
that. I am working on a report writer, and wanted to issue multiple
calls to
a single data object. I wanted to ensure that I didn't accidentally
create
that object more than once, and if I did, I would just use the one
already
existing. I tested it and verified that avoiding the calls to create a
new
SQLConnection object repeatedly did save time. (I want to reuse the
connection, since I'm not caching the data...already tried it that way,
and
because the possible records returned are in the tens of thousands,
sending
numerous highly targeted parameterized queries is much more efficient
than
pulling all over and navigating them via DataViews) I have not delved
into
the guts of the .Net Framework yet...just C# and ASP.Net, so that is
why I'm
unclear on many of these issues regarding app boundaries and whatnot.

-----Original Message-----
From: Jim Arnold [mailto:Click here to reveal e-mail address]
Sent: Monday, January 28, 2002 12:46 PM
To: ngfx-patterns
Subject: [ngfx-patterns] RE: Problem with Singleton object instance

Static member variables (of which a Singleton is usually one) exist
across
applications so yes, all objects in an ASP.Net application boundary
will
share the same instance. If you want one instance per page, it's not
a
Singleton, it's just an object. What are you trying to achieve?

Jim

[Original message clipped]

| [ngfx-patterns] member Click here to reveal e-mail address = YOUR ID
| http://www.aspfriends.com/aspfriends/ngfx-patterns.asp = JOIN/QUIT

| [ngfx-patterns] member Click here to reveal e-mail address = YOUR ID
| http://www.aspfriends.com/aspfriends/ngfx-patterns.asp = JOIN/QUIT

| [ngfx-patterns] member Click here to reveal e-mail address = YOUR ID
| http://www.aspfriends.com/aspfriends/ngfx-patterns.asp = JOIN/QUIT

Reply to this message...
 
 
System.Configuration.ConfigurationSettings
System.Data.CommandType
System.Data.ConnectionState
System.Data.DataSet
System.Data.SqlClient.SqlCommand
System.Data.SqlClient.SqlConnection
System.Data.SqlClient.SqlDataAdapter
System.EventArgs
System.EventHandler
System.Exception
System.Web.UI.Page




ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
Ad


Need Dot Net Interview Questions?
Ask ExamGuru, Inc. for advice and help on Passing .Net Interviews
.Net Projects
Best-of-breed application framework for .NET projects, developed by ExamGuru, Inc. and ExamGuru IT
Free .net Help
Commission ExamGuru, Inc. and his team for your next bespoke software project
FogBUGZ
The only bug tracking system carefully crafted with one goal in mind: helping teams create great software.
Awesome Tools
If you don't know about these, you're missing out... IT Certification Questions
IT Interview Questions
Free Oracle 10g Training
MCSE Boortcamp
Cisco Study Guides
Cheap Study Guides
Exact Questions
Dot Net Interview Questions
Oracle OCP
Cheap Travel
Designer Perfumes - Wholesale Prices
Free Programming Tutorials
 
ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
 Copyright © ExamGuru, Inc. 2001-2006
Contact Us - Terms of Use - Privacy Policy - www.dot-net-guru.com - www.examguru.net - www.oraclesource.net - www.itinterviews.net - www.examguru.net/ITCertification