Session management on web farm with sql server

W

wdudek

We have a website that works fine when hosted on a single server, however
it experiences some strange problems when run on a web farm using SQL Server
to handle session state. When running on the farm, in the same method call an
object that just had a value set will no longer have the value set a
couple of lines later. In this example the object is pulled out of session,
altered and placed back in session before a following line of code tries to
use
the altered value, only to find out that it appears to have never been
changed. The application essentially stores 1 object that contains several
other
objects in session. The group that manages teh web farm is telling me that
this is the problem. They are saying that because of the
serialization/deserialization in sql server, the reference to the inner
objects isn't flowing through to the object being stored in SQL Server. Does
this sound correct? Should there be any differance between how a website code
funcitons on a single server versus a web farm? They provided me with the
below documentation, but have not yet been able to tell me where it came
from. This has been an ongoing battle over who's problem it really is, any
information on this subject will be appreciated. Also as a note all of the
objects are serializable.

Thanks,

Bill

This is the reponse I got from our techincal support group There is no
problem with the SQL Server settings for storing the session as session
objects get created, retrieved and updated in the SQL Server. The issue is
with the way the session object is updated in the C# code.

Session in asp.net behaves as follows.

InProc: In this mode session data is stored in the AppDomain of the
application. All the objects stored in the session are actually stored in
AppDomain and a reference is created for the session.

SQL Server/State Server: In this mode session data is serialized and
stored
in SQL server database. When sessions is loaded system will fetch the data
from database and deserialize it and creates the objects with deserialize
data and bind them to state bag. In this mode the actual object references
and session object references are different.

Because of this, the S&S application is able to retrieve data when session
is in InProc but not in SQL Server. What's happening in S&S application is
as
below.

In case of InProc session Inquiry object and Search object
have
same reference, so updating one object is will show effect all its
references.

In case of SQL Server session each object will have its own
reference (each time new object is created from deserialize data), so
updating one object will not update the other object in the session.

To solve this, C# code needs to be modified where the session related
objects are updated such that it gets updated in the session correctly.
 
B

bruce barker

session is a collection of objects. with in proc, this collection is a static
collection. with out-of-proc session managers (like sqlsession), the session
collection is an instance collection tired to the request. at the end of the
request, it serialized out to the store. at the start of the request, its
deserialied from the store. during request processing, there is no difference
between inproc and out-of-proc sessions.

if you see a difference. then you object is not serializing/deserializing
correctly. you will have to fix the logic. the most common issue, is not
handling mulitple to references to the same object correctly.

simple example:

// first request

myObject obj = new myObject();
List<myObject> list = new List<myObject>();
list.Add(obj);
list.Add(obj);
Session["list"] = list;
list[0].Value="1"; // list[0].Value == list[1].Value == "1";
list[0].Value="2"; // list[0].Value == list[1].Value == "2";


// next request

List<myObject> list = (myObject) Session["list'];
list[0]="3"; // list[0].Value != list[1].Value

this is because at serialzztion time list[0] & list[1] where deserialized.
when deserialiezed, two objects were created, but each with the same value.
now changing one does not change the other.

so, if your object has mutiple refences to the same object (say the same
object is in two collections) then you have to write a custom serializer.

the approach i use for complex objects I store in session, is there is a
base collection that objects belong to, and other references just serialize
the lookup key.

-- bruce (sqlwork.com)
 
W

wdudek

Thanks,
This explains exactly what is happening. I can look this up, but is
anyone aware of any links that discuss this issue in more depth? I understand
the concept of custom serialization but have never worked with it.

Thanks again

Bill

bruce barker said:
session is a collection of objects. with in proc, this collection is a static
collection. with out-of-proc session managers (like sqlsession), the session
collection is an instance collection tired to the request. at the end of the
request, it serialized out to the store. at the start of the request, its
deserialied from the store. during request processing, there is no difference
between inproc and out-of-proc sessions.

if you see a difference. then you object is not serializing/deserializing
correctly. you will have to fix the logic. the most common issue, is not
handling mulitple to references to the same object correctly.

simple example:

// first request

myObject obj = new myObject();
List<myObject> list = new List<myObject>();
list.Add(obj);
list.Add(obj);
Session["list"] = list;
list[0].Value="1"; // list[0].Value == list[1].Value == "1";
list[0].Value="2"; // list[0].Value == list[1].Value == "2";


// next request

List<myObject> list = (myObject) Session["list'];
list[0]="3"; // list[0].Value != list[1].Value

this is because at serialzztion time list[0] & list[1] where deserialized.
when deserialiezed, two objects were created, but each with the same value.
now changing one does not change the other.

so, if your object has mutiple refences to the same object (say the same
object is in two collections) then you have to write a custom serializer.

the approach i use for complex objects I store in session, is there is a
base collection that objects belong to, and other references just serialize
the lookup key.

-- bruce (sqlwork.com)


wdudek said:
We have a website that works fine when hosted on a single server, however
it experiences some strange problems when run on a web farm using SQL Server
to handle session state. When running on the farm, in the same method call an
object that just had a value set will no longer have the value set a
couple of lines later. In this example the object is pulled out of session,
altered and placed back in session before a following line of code tries to
use
the altered value, only to find out that it appears to have never been
changed. The application essentially stores 1 object that contains several
other
objects in session. The group that manages teh web farm is telling me that
this is the problem. They are saying that because of the
serialization/deserialization in sql server, the reference to the inner
objects isn't flowing through to the object being stored in SQL Server. Does
this sound correct? Should there be any differance between how a website code
funcitons on a single server versus a web farm? They provided me with the
below documentation, but have not yet been able to tell me where it came
from. This has been an ongoing battle over who's problem it really is, any
information on this subject will be appreciated. Also as a note all of the
objects are serializable.

Thanks,

Bill

This is the reponse I got from our techincal support group There is no
problem with the SQL Server settings for storing the session as session
objects get created, retrieved and updated in the SQL Server. The issue is
with the way the session object is updated in the C# code.

Session in asp.net behaves as follows.

InProc: In this mode session data is stored in the AppDomain of the
application. All the objects stored in the session are actually stored in
AppDomain and a reference is created for the session.

SQL Server/State Server: In this mode session data is serialized and
stored
in SQL server database. When sessions is loaded system will fetch the data
from database and deserialize it and creates the objects with deserialize
data and bind them to state bag. In this mode the actual object references
and session object references are different.

Because of this, the S&S application is able to retrieve data when session
is in InProc but not in SQL Server. What's happening in S&S application is
as
below.

In case of InProc session Inquiry object and Search object
have
same reference, so updating one object is will show effect all its
references.

In case of SQL Server session each object will have its own
reference (each time new object is created from deserialize data), so
updating one object will not update the other object in the session.

To solve this, C# code needs to be modified where the session related
objects are updated such that it gets updated in the session correctly.
 
S

Steven Cheng

Hi Bill,

For binary serialization and implement your custom serialization approach,
here are some reference that should be helpful:

#Run-time Serialization
http://msdn.microsoft.com/msdnmag/issues/02/04/net/

#Serialization in the .NET Framework
http://www.15seconds.com/issue/020903.htm


Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.

--------------------
From: =?Utf-8?B?d2R1ZGVr?= <[email protected]>
References: <[email protected]>
Subject: RE: Session management on web farm with sql server
Date: Thu, 28 Feb 2008 10:57:02 -0800
Thanks,
This explains exactly what is happening. I can look this up, but is
anyone aware of any links that discuss this issue in more depth? I understand
the concept of custom serialization but have never worked with it.

Thanks again

Bill

bruce barker said:
session is a collection of objects. with in proc, this collection is a static
collection. with out-of-proc session managers (like sqlsession), the session
collection is an instance collection tired to the request. at the end of the
request, it serialized out to the store. at the start of the request, its
deserialied from the store. during request processing, there is no difference
between inproc and out-of-proc sessions.

if you see a difference. then you object is not serializing/deserializing
correctly. you will have to fix the logic. the most common issue, is not
handling mulitple to references to the same object correctly.

simple example:

// first request

myObject obj = new myObject();
List<myObject> list = new List<myObject>();
list.Add(obj);
list.Add(obj);
Session["list"] = list;
list[0].Value="1"; // list[0].Value == list[1].Value == "1";
list[0].Value="2"; // list[0].Value == list[1].Value == "2";


// next request

List<myObject> list = (myObject) Session["list'];
list[0]="3"; // list[0].Value != list[1].Value

this is because at serialzztion time list[0] & list[1] where deserialized.
when deserialiezed, two objects were created, but each with the same value.
now changing one does not change the other.

so, if your object has mutiple refences to the same object (say the same
object is in two collections) then you have to write a custom serializer.

the approach i use for complex objects I store in session, is there is a
base collection that objects belong to, and other references just serialize
the lookup key.

-- bruce (sqlwork.com)


wdudek said:
We have a website that works fine when hosted on a single server, however
it experiences some strange problems when run on a web farm using SQL Server
to handle session state. When running on the farm, in the same method call an
object that just had a value set will no longer have the value set a
couple of lines later. In this example the object is pulled out of session,
altered and placed back in session before a following line of code tries to
use
the altered value, only to find out that it appears to have never been
changed. The application essentially stores 1 object that contains several
other
objects in session. The group that manages teh web farm is telling me that
this is the problem. They are saying that because of the
serialization/deserialization in sql server, the reference to the inner
objects isn't flowing through to the object being stored in SQL Server. Does
this sound correct? Should there be any differance between how a website code
funcitons on a single server versus a web farm? They provided me with the
below documentation, but have not yet been able to tell me where it came
from. This has been an ongoing battle over who's problem it really is, any
information on this subject will be appreciated. Also as a note all of the
objects are serializable.

Thanks,

Bill

This is the reponse I got from our techincal support group There is no
problem with the SQL Server settings for storing the session as session
objects get created, retrieved and updated in the SQL Server. The issue is
with the way the session object is updated in the C# code.

Session in asp.net behaves as follows.

InProc: In this mode session data is stored in the AppDomain of the
application. All the objects stored in the session are actually stored in
AppDomain and a reference is created for the session.

SQL Server/State Server: In this mode session data is serialized and
stored
in SQL server database. When sessions is loaded system will fetch the data
from database and deserialize it and creates the objects with deserialize
data and bind them to state bag. In this mode the actual object references
and session object references are different.

Because of this, the S&S application is able to retrieve data when session
is in InProc but not in SQL Server. What's happening in S&S application is
as
below.

In case of InProc session Inquiry object and Search object
have
same reference, so updating one object is will show effect all its
references.

In case of SQL Server session each object will have its own
reference (each time new object is created from deserialize data), so
updating one object will not update the other object in the session.

To solve this, C# code needs to be modified where the session related
objects are updated such that it gets updated in the session correctly.
 
W

wdudek

Thanks,

There isn't much out there regarding this problem. My background is more
windows oriented than web, but it seems that if web sites really are going to
replace the desktop application as allot of people would have you believe
that this particular issue would come up more often. Just my 2 cents, but
thanks again for the links I'll take a look.

Bill

"Steven Cheng" said:
Hi Bill,

For binary serialization and implement your custom serialization approach,
here are some reference that should be helpful:

#Run-time Serialization
http://msdn.microsoft.com/msdnmag/issues/02/04/net/

#Serialization in the .NET Framework
http://www.15seconds.com/issue/020903.htm


Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.

--------------------
From: =?Utf-8?B?d2R1ZGVr?= <[email protected]>
References: <[email protected]>
Subject: RE: Session management on web farm with sql server
Date: Thu, 28 Feb 2008 10:57:02 -0800
Thanks,
This explains exactly what is happening. I can look this up, but is
anyone aware of any links that discuss this issue in more depth? I understand
the concept of custom serialization but have never worked with it.

Thanks again

Bill

bruce barker said:
session is a collection of objects. with in proc, this collection is a static
collection. with out-of-proc session managers (like sqlsession), the session
collection is an instance collection tired to the request. at the end of the
request, it serialized out to the store. at the start of the request, its
deserialied from the store. during request processing, there is no difference
between inproc and out-of-proc sessions.

if you see a difference. then you object is not serializing/deserializing
correctly. you will have to fix the logic. the most common issue, is not
handling mulitple to references to the same object correctly.

simple example:

// first request

myObject obj = new myObject();
List<myObject> list = new List<myObject>();
list.Add(obj);
list.Add(obj);
Session["list"] = list;
list[0].Value="1"; // list[0].Value == list[1].Value == "1";
list[0].Value="2"; // list[0].Value == list[1].Value == "2";


// next request

List<myObject> list = (myObject) Session["list'];
list[0]="3"; // list[0].Value != list[1].Value

this is because at serialzztion time list[0] & list[1] where deserialized.
when deserialiezed, two objects were created, but each with the same value.
now changing one does not change the other.

so, if your object has mutiple refences to the same object (say the same
object is in two collections) then you have to write a custom serializer.

the approach i use for complex objects I store in session, is there is a
base collection that objects belong to, and other references just serialize
the lookup key.

-- bruce (sqlwork.com)


:

We have a website that works fine when hosted on a single server, however
it experiences some strange problems when run on a web farm using SQL Server
to handle session state. When running on the farm, in the same method call an
object that just had a value set will no longer have the value set a
couple of lines later. In this example the object is pulled out of session,
altered and placed back in session before a following line of code tries to
use
the altered value, only to find out that it appears to have never been
changed. The application essentially stores 1 object that contains several
other
objects in session. The group that manages teh web farm is telling me that
this is the problem. They are saying that because of the
serialization/deserialization in sql server, the reference to the inner
objects isn't flowing through to the object being stored in SQL Server. Does
this sound correct? Should there be any differance between how a website code
funcitons on a single server versus a web farm? They provided me with the
below documentation, but have not yet been able to tell me where it came
from. This has been an ongoing battle over who's problem it really is, any
information on this subject will be appreciated. Also as a note all of the
objects are serializable.

Thanks,

Bill

This is the reponse I got from our techincal support group There is no
problem with the SQL Server settings for storing the session as session
objects get created, retrieved and updated in the SQL Server. The issue is
with the way the session object is updated in the C# code.

Session in asp.net behaves as follows.

InProc: In this mode session data is stored in the AppDomain of the
application. All the objects stored in the session are actually stored in
AppDomain and a reference is created for the session.

SQL Server/State Server: In this mode session data is serialized and
stored
in SQL server database. When sessions is loaded system will fetch the data
from database and deserialize it and creates the objects with deserialize
data and bind them to state bag. In this mode the actual object references
and session object references are different.

Because of this, the S&S application is able to retrieve data when session
is in InProc but not in SQL Server. What's happening in S&S application is
as
below.

In case of InProc session Inquiry object and Search object
have
same reference, so updating one object is will show effect all its
references.

In case of SQL Server session each object will have its own
reference (each time new object is created from deserialize data), so
updating one object will not update the other object in the session.

To solve this, C# code needs to be modified where the session related
objects are updated such that it gets updated in the session correctly.
 
S

Steven Cheng

Thanks for your followup Bill,

For serialization, since winform/desktop application can hold most objects
in memory while ASP.NET web application is stateless(request, response
based) and may work between client and server machines, serialization plays
more important role here.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.


--------------------
From: =?Utf-8?B?d2R1ZGVr?= <[email protected]>
References: <[email protected]>
<[email protected]>
Subject: RE: Session management on web farm with sql server
Date: Fri, 29 Feb 2008 08:56:04 -0800
Thanks,

There isn't much out there regarding this problem. My background is more
windows oriented than web, but it seems that if web sites really are going to
replace the desktop application as allot of people would have you believe
that this particular issue would come up more often. Just my 2 cents, but
thanks again for the links I'll take a look.

Bill

"Steven Cheng" said:
Hi Bill,

For binary serialization and implement your custom serialization approach,
here are some reference that should be helpful:

#Run-time Serialization
http://msdn.microsoft.com/msdnmag/issues/02/04/net/

#Serialization in the .NET Framework
http://www.15seconds.com/issue/020903.htm


Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.

--------------------
From: =?Utf-8?B?d2R1ZGVr?= <[email protected]>
References: <[email protected]>
Subject: RE: Session management on web farm with sql server
Date: Thu, 28 Feb 2008 10:57:02 -0800
Thanks,
This explains exactly what is happening. I can look this up, but is
anyone aware of any links that discuss this issue in more depth? I understand
the concept of custom serialization but have never worked with it.

Thanks again

Bill

:

session is a collection of objects. with in proc, this collection is
a
static
collection. with out-of-proc session managers (like sqlsession), the session
collection is an instance collection tired to the request. at the end
of
the
request, it serialized out to the store. at the start of the request, its
deserialied from the store. during request processing, there is no difference
between inproc and out-of-proc sessions.

if you see a difference. then you object is not serializing/deserializing
correctly. you will have to fix the logic. the most common issue, is not
handling mulitple to references to the same object correctly.

simple example:

// first request

myObject obj = new myObject();
List<myObject> list = new List<myObject>();
list.Add(obj);
list.Add(obj);
Session["list"] = list;
list[0].Value="1"; // list[0].Value == list[1].Value == "1";
list[0].Value="2"; // list[0].Value == list[1].Value == "2";


// next request

List<myObject> list = (myObject) Session["list'];
list[0]="3"; // list[0].Value != list[1].Value

this is because at serialzztion time list[0] & list[1] where deserialized.
when deserialiezed, two objects were created, but each with the same value.
now changing one does not change the other.

so, if your object has mutiple refences to the same object (say the same
object is in two collections) then you have to write a custom serializer.

the approach i use for complex objects I store in session, is there is a
base collection that objects belong to, and other references just serialize
the lookup key.

-- bruce (sqlwork.com)


:

We have a website that works fine when hosted on a single server, however
it experiences some strange problems when run on a web farm using
SQL
Server
to handle session state. When running on the farm, in the same
method
call an
object that just had a value set will no longer have the value set a
couple of lines later. In this example the object is pulled out of session,
altered and placed back in session before a following line of code tries to
use
the altered value, only to find out that it appears to have never been
changed. The application essentially stores 1 object that contains several
other
objects in session. The group that manages teh web farm is telling
me
that
this is the problem. They are saying that because of the
serialization/deserialization in sql server, the reference to the inner
objects isn't flowing through to the object being stored in SQL Server. Does
this sound correct? Should there be any differance between how a website code
funcitons on a single server versus a web farm? They provided me
with
the
below documentation, but have not yet been able to tell me where it came
from. This has been an ongoing battle over who's problem it really
is,
any
information on this subject will be appreciated. Also as a note all
of
the
objects are serializable.

Thanks,

Bill

This is the reponse I got from our techincal support group There is no
problem with the SQL Server settings for storing the session as session
objects get created, retrieved and updated in the SQL Server. The issue is
with the way the session object is updated in the C# code.

Session in asp.net behaves as follows.

InProc: In this mode session data is stored in the AppDomain of the
application. All the objects stored in the session are actually
stored
in
AppDomain and a reference is created for the session.

SQL Server/State Server: In this mode session data is serialized and
stored
in SQL server database. When sessions is loaded system will fetch
the
data
from database and deserialize it and creates the objects with deserialize
data and bind them to state bag. In this mode the actual object references
and session object references are different.

Because of this, the S&S application is able to retrieve data when session
is in InProc but not in SQL Server. What's happening in S&S application is
as
below.

In case of InProc session Inquiry object and Search object
have
same reference, so updating one object is will show effect all its
references.

In case of SQL Server session each object will have its own
reference (each time new object is created from deserialize data), so
updating one object will not update the other object in the session.

To solve this, C# code needs to be modified where the session related
objects are updated such that it gets updated in the session correctly.
 
N

Nathan

Steven:

I am having a similar problem to Bill.

My web application works correctly when running with In Process Session
State, but loses data when running with SQL Server Session State. After
weeks of debugging, using the VS 2005 debugger and adding code to log
object/variable states to a file, it appears that when I change the content
of a collection which is referenced by an object stored in Session, the
update is only recognized while running with In Process Session State.

I am guessing that the session serialization code only checks the root
object for changes (if that) before deciding whether to re-serialize that
object and sending it to the session database. As a result, my changes are
never stored in the session database and cannot be de-serialized when the
page posts back or I move on to the next page.

Do you know whether this is correct? If so, how do I work around it so my
changes to subordinate objects are propogated to session? If not, what else
should I look for and what else could I do to ensure my changes get stored
into the session database?


Thanks,
Nathan


"Steven Cheng" said:
Thanks for your followup Bill,

For serialization, since winform/desktop application can hold most objects
in memory while ASP.NET web application is stateless(request, response
based) and may work between client and server machines, serialization
plays
more important role here.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no
rights.


--------------------
From: =?Utf-8?B?d2R1ZGVr?= <[email protected]>
References: <[email protected]>
<[email protected]>
Subject: RE: Session management on web farm with sql server
Date: Fri, 29 Feb 2008 08:56:04 -0800
Thanks,

There isn't much out there regarding this problem. My background is more
windows oriented than web, but it seems that if web sites really are going to
replace the desktop application as allot of people would have you believe
that this particular issue would come up more often. Just my 2 cents, but
thanks again for the links I'll take a look.

Bill

"Steven Cheng" said:
Hi Bill,

For binary serialization and implement your custom serialization approach,
here are some reference that should be helpful:

#Run-time Serialization
http://msdn.microsoft.com/msdnmag/issues/02/04/net/

#Serialization in the .NET Framework
http://www.15seconds.com/issue/020903.htm


Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.

--------------------
From: =?Utf-8?B?d2R1ZGVr?= <[email protected]>
References: <[email protected]>
<[email protected]>
Subject: RE: Session management on web farm with sql server
Date: Thu, 28 Feb 2008 10:57:02 -0800


Thanks,
This explains exactly what is happening. I can look this up, but is
anyone aware of any links that discuss this issue in more depth? I
understand
the concept of custom serialization but have never worked with it.

Thanks again

Bill

:

session is a collection of objects. with in proc, this collection is a
static
collection. with out-of-proc session managers (like sqlsession), the
session
collection is an instance collection tired to the request. at the end of
the
request, it serialized out to the store. at the start of the request,
its
deserialied from the store. during request processing, there is no
difference
between inproc and out-of-proc sessions.

if you see a difference. then you object is not
serializing/deserializing
correctly. you will have to fix the logic. the most common issue, is not
handling mulitple to references to the same object correctly.

simple example:

// first request

myObject obj = new myObject();
List<myObject> list = new List<myObject>();
list.Add(obj);
list.Add(obj);
Session["list"] = list;
list[0].Value="1"; // list[0].Value == list[1].Value == "1";
list[0].Value="2"; // list[0].Value == list[1].Value == "2";


// next request

List<myObject> list = (myObject) Session["list'];
list[0]="3"; // list[0].Value != list[1].Value

this is because at serialzztion time list[0] & list[1] where
deserialized.
when deserialiezed, two objects were created, but each with the same
value.
now changing one does not change the other.

so, if your object has mutiple refences to the same object (say the same
object is in two collections) then you have to write a custom serializer.

the approach i use for complex objects I store in session, is there is a
base collection that objects belong to, and other references just
serialize
the lookup key.

-- bruce (sqlwork.com)


:

We have a website that works fine when hosted on a single server,
however
it experiences some strange problems when run on a web farm using SQL
Server
to handle session state. When running on the farm, in the same method
call an
object that just had a value set will no longer have the value set a
couple of lines later. In this example the object is pulled out of
session,
altered and placed back in session before a following line of code
tries to
use
the altered value, only to find out that it appears to have never been
changed. The application essentially stores 1 object that contains
several
other
objects in session. The group that manages teh web farm is telling me
that
this is the problem. They are saying that because of the
serialization/deserialization in sql server, the reference to the
inner
objects isn't flowing through to the object being stored in SQL
Server. Does
this sound correct? Should there be any differance between how a
website code
funcitons on a single server versus a web farm? They provided me with
the
below documentation, but have not yet been able to tell me where it
came
from. This has been an ongoing battle over who's problem it really is,
any
information on this subject will be appreciated. Also as a note all of
the
objects are serializable.

Thanks,

Bill

This is the reponse I got from our techincal support group There is no
problem with the SQL Server settings for storing the session as
session
objects get created, retrieved and updated in the SQL Server. The
issue is
with the way the session object is updated in the C# code.

Session in asp.net behaves as follows.

InProc: In this mode session data is stored in the AppDomain of the
application. All the objects stored in the session are actually stored
in
AppDomain and a reference is created for the session.

SQL Server/State Server: In this mode session data is serialized and
stored
in SQL server database. When sessions is loaded system will fetch the
data
from database and deserialize it and creates the objects with
deserialize
data and bind them to state bag. In this mode the actual object
references
and session object references are different.

Because of this, the S&S application is able to retrieve data when
session
is in InProc but not in SQL Server. What's happening in S&S
application is
as
below.

In case of InProc session Inquiry object and Search object
have
same reference, so updating one object is will show effect all its
references.

In case of SQL Server session each object will have its
own
reference (each time new object is created from deserialize data), so
updating one object will not update the other object in the
session.

To solve this, C# code needs to be modified where the session related
objects are updated such that it gets updated in the session
correctly.
 
S

Steven Cheng

Thanks for your input Nathan,

Yes, I think you're running into the same problem. Bruce's explanation is
quite good, here is his previous reply for your reference:

================
session is a collection of objects. with in proc, this collection is a
static
collection. with out-of-proc session managers (like sqlsession), the
session
collection is an instance collection tired to the request. at the end of
the
request, it serialized out to the store. at the start of the request, its
deserialied from the store. during request processing, there is no
difference
between inproc and out-of-proc sessions.

if you see a difference. then you object is not serializing/deserializing
correctly. you will have to fix the logic. the most common issue, is not
handling mulitple to references to the same object correctly.

simple example:

// first request

myObject obj = new myObject();
List<myObject> list = new List<myObject>();
list.Add(obj);
list.Add(obj);
Session["list"] = list;
list[0].Value="1"; // list[0].Value == list[1].Value == "1";
list[0].Value="2"; // list[0].Value == list[1].Value == "2";


// next request

List<myObject> list = (myObject) Session["list'];
list[0]="3"; // list[0].Value != list[1].Value

this is because at serialzztion time list[0] & list[1] where deserialized.
when deserialiezed, two objects were created, but each with the same value.
now changing one does not change the other.

so, if your object has mutiple refences to the same object (say the same
object is in two collections) then you have to write a custom serializer.

the approach i use for complex objects I store in session, is there is a
base collection that objects belong to, and other references just serialize
the lookup key.

-- bruce (sqlwork.com)
================================

to resolve this, you can consider:

1. change the data structure you use and avoid nested class members of
reference type.

2. add custom binary serialization for your class. For example, for those
class members that originally stored as reference, you may need to always
serialize them into a value type data (such as a byte array or a string) so
that you can ensure it is always copied and updated with the root object.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.




--------------------
 
N

Nathan

I inherited the application I am working with. When it was written, the original author(s) freely stored complex custom objects in session, fully expecting their component objects to also be stored and readily accessed after posting back the current page or navigating to new pages. Because the application was written using "In Process" session state, everything worked -- until we put it in a load balanced server farm.

To make the application work with "out of process" session state, I marked every class [Serializable] and manually coded an implementation of the ISerializable interface -- both the GetObjectData method and a de-serialization constructor. In the GetObjectData method, I call the SerializationInfo.AddValue(string, object, Type) method for each field of the class. For collections, I call custom methods that iterate through each element, modifying the identifier string with the collection indices. In the de-serialization constructor, I do the reverse calling the SerializationInfo.GetValue(string, Type) method and casting as appropriate.

Example:

[Serializable]
class MyClass : MyBase, ISerializable {
public MyClass () {
}
public MyClass(SerializationInfo Info, StreamingContext Context) : base(Info, Context) {
_field = ()Info.GetValue("field", typeof());
_propertiesList = MiscUtilities.DeserializeHashtable("propertiesList", Info, Context);
}

private MyOtherClass _field = null;
public MyOtherClass Field {
get { return _field; }
set { _field = value; }
}

private Hashtable _propertiesList = new Hashtable();
public MyBase this[string key] {
get { return (MyBase)_propertiesList[key]; }
set { if (value is MyBase) { _propertiesList[key] = value; } }
}

public void GetObjectData(SerializationInfo Info, StreamingContext Context){
base.GetObjectData(Info, Context);
Info.AddValue("field", _field, typeof());
MiscUtilities.SerializeHashtable("propertiesList", _propertiesList, Info, Context);
}
}

class MyBase : ISerializable {
// constructors
MyBase(){};
MyBase(..., ...) {...};
// fields & properties
// methods
GetObjectData(..., ...) {...};
}

class MyOtherClass : MyBase, ISerializable {
// constructors
MyBase(){};
MyBase(..., ...) {...};
// fields & properties
// methods
GetObjectData(..., ...) {...};
}

class MiscUtilities {
SerializeHashtable(string name, Hashtable table, SerializationInfo Info, StreamingContext Context) {
int length = table.Count;
Info.AddValue(name + ".length", length, typeof(int));
int i = 0;
foreach(DictionaryEntry entry in table) {
Info.AddValue(name + "[" + i.ToString() + "].key", entry.Key, typeof(string));
Type valueType = (entry.Value != null) ? entry.Value.GetType() : typeof(null);
Info.AddValue(name + "[" + i.ToString() + "].valueType", valueType, typeof(Type));
Info.AddValue(name + "[" + i.ToString() + "].value", entry.Value, valueType);
}
}
DeserializeHashtable(string name, SerializationInfo Info, StreamingContext Context) {
Hashtable hOut = new Hashtable();
int length = Info.GetInt32(name + ".length");
for(int i = 0; i < length; i++) {
string key = Info.GetString(name + "[" + i.ToString() + "].key", typeof(string));
Type valueType = (Type)Info.GetValue(name + "[" + i.ToString() + "].valueType", typeof(Type));
object value = Info.GetValue(name + "[" + i.ToString() + "].value", valueType);
hOut[key] = value;
}
return hOut;
}
// other collection serialization and de-serialization routines (ArrayList, ICollection, IDictionary, ...)
}

The above code is a very simplified example of what I am actually working with, but I think it conveys the idea that I have manually implemented the ISerializable interface to ensure each field of every custom object gets properly serialized and de-serialized. But I am still losing data between postbacks and during page navigation which should have been stored in session. While running the debugger, I set breakpoints in the "GetObjectData" methods of the disappearing objects -- the debugger never stops in those objects' GetObjectData methods. The objects are stored in a custom collection, which is attached to yet another custom object and that object is the one placed into session.

From the documentation I have read, I believe the binary formatter is supposed to traverse the object graph from the topmost object all the way down to the bottom until every referenced object and collection has been serialized. How come that is not happening? The top level object, which is directly placed into session gets serialized and deserialized, but the collections and objects it references don't seem to make it. What am I missing?

Somewhere in code:

MyClass MyObject = new MyClass();
// MyObject properties are set, collections are filled,

Later, in code references are made and passed to MyObject as various methods operate on it or pass it on to another method.
Eventually, a reference to MyObject is passed to function that stores it in session.

public void SomeMethod(MyBase obj) {
// ...
Session["MyObject"] = obj;
// ...
}

When following along with the debugger, it seems that "obj" really is "MyObject". It has all the same values, it references all the same objects and collections, its collections reference the same set of objects; all the changes as methods operated on it and its components are still present. However, when I write the Session object's contents to a log file, after Session["MyObject"] has been set to "obj", the content of Session["MyObject"] has lost changes that were made to MyObject's components. Collections are reset to a previous state and component objects may also have lost their updates. What is going on? If I run the application with "In Process" session state the updates remain after placing the top level object into session -- they only disappear when running with "out of process" session state.
 
S

Steven Cheng

Hi Nathan,

I think the problem here may be due to the collection class or any other
further container class that will hold reference to your custom objects.
Yes, you've implemented custom class's serialziation. However, for webfarm
sql session state scenario, as Bruce has mentioned that you need to take
care of the root class objects stored in session. For example, if some
other class instance(which contains your custom type as member) is stored
in session, you will need to take care of the serialization from that
class(provide a customer wrapper class that implement custom
serialziation). Also, have you tried put your custom class object directly
in session rather than some base class reference to see whether it works?

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.


--------------------
Subject: Re: Session management on web farm with sql server
Date: Tue, 4 Mar 2008 18:04:04 -0600
I inherited the application I am working with. When it was written, the
original author(s) freely stored complex custom objects in session, fully
expecting their component objects to also be stored and readily accessed
after posting back the current page or navigating to new pages. Because the
application was written using "In Process" session state, everything worked
-- until we put it in a load balanced server farm.
To make the application work with "out of process" session state, I marked
every class [Serializable] and manually coded an implementation of the
ISerializable interface -- both the GetObjectData method and a
de-serialization constructor. In the GetObjectData method, I call the
SerializationInfo.AddValue(string, object, Type) method for each field of
the class. For collections, I call custom methods that iterate through
each element, modifying the identifier string with the collection indices.
In the de-serialization constructor, I do the reverse calling the
SerializationInfo.GetValue(string, Type) method and casting as appropriate.
Example:
[Serializable]
class MyClass : MyBase, ISerializable {
public MyClass () {
}
public MyClass(SerializationInfo Info, StreamingContext Context) : base(Info, Context) {
_field = ()Info.GetValue("field", typeof());
_propertiesList =
MiscUtilities.DeserializeHashtable("propertiesList", Info, Context);
}
private MyOtherClass _field = null;
public MyOtherClass Field {
get { return _field; }
set { _field = value; }
}
private Hashtable _propertiesList = new Hashtable();
public MyBase this[string key] {
get { return (MyBase)_propertiesList[key]; }
set { if (value is MyBase) { _propertiesList[key] = value; } }
}
public void GetObjectData(SerializationInfo Info, StreamingContext Context){
base.GetObjectData(Info, Context);
Info.AddValue("field", _field, typeof());
MiscUtilities.SerializeHashtable("propertiesList",
_propertiesList, Info, Context);
}
}
class MyBase : ISerializable {
// constructors
MyBase(){};
MyBase(..., ...) {...};
// fields & properties
// methods
GetObjectData(..., ...) {...};
}
class MyOtherClass : MyBase, ISerializable {
// constructors
MyBase(){};
MyBase(..., ...) {...};
// fields & properties
// methods
GetObjectData(..., ...) {...};
}
class MiscUtilities {
SerializeHashtable(string name, Hashtable table, SerializationInfo
Info, StreamingContext Context) {
int length = table.Count;
Info.AddValue(name + ".length", length, typeof(int));
int i = 0;
foreach(DictionaryEntry entry in table) {
Info.AddValue(name + "[" + i.ToString() + "].key", entry.Key, typeof(string));
Type valueType = (entry.Value != null) ? entry.Value.GetType() : typeof(null);
Info.AddValue(name + "[" + i.ToString() + "].valueType", valueType, typeof(Type));
Info.AddValue(name + "[" + i.ToString() + "].value", entry.Value, valueType);
}
}
DeserializeHashtable(string name, SerializationInfo Info, StreamingContext Context) {
Hashtable hOut = new Hashtable();
int length = Info.GetInt32(name + ".length");
for(int i = 0; i < length; i++) {
string key = Info.GetString(name + "[" + i.ToString() + "].key", typeof(string));
Type valueType = (Type)Info.GetValue(name + "[" + i.ToString()
+ "].valueType", typeof(Type));
object value = Info.GetValue(name + "[" + i.ToString() + "].value", valueType);
hOut[key] = value;
}
return hOut;
}
// other collection serialization and de-serialization routines
(ArrayList, ICollection, IDictionary, ...)
}
The above code is a very simplified example of what I am actually working
with, but I think it conveys the idea that I have manually implemented the
ISerializable interface to ensure each field of every custom object gets
properly serialized and de-serialized. But I am still losing data between
postbacks and during page navigation which should have been stored in
session. While running the debugger, I set breakpoints in the
"GetObjectData" methods of the disappearing objects -- the debugger never
stops in those objects' GetObjectData methods. The objects are stored in a
custom collection, which is attached to yet another custom object and that
object is the one placed into session.
From the documentation I have read, I believe the binary formatter is
supposed to traverse the object graph from the topmost object all the way
down to the bottom until every referenced object and collection has been
serialized. How come that is not happening? The top level object, which
is directly placed into session gets serialized and deserialized, but the
collections and objects it references don't seem to make it. What am I
missing?
Somewhere in code:
MyClass MyObject = new MyClass();
// MyObject properties are set, collections are filled,
Later, in code references are made and passed to MyObject as various
methods operate on it or pass it on to another method.
Eventually, a reference to MyObject is passed to function that stores it in session.
public void SomeMethod(MyBase obj) {
// ...
Session["MyObject"] = obj;
// ...
}
When following along with the debugger, it seems that "obj" really is
"MyObject". It has all the same values, it references all the same objects
and collections, its collections reference the same set of objects; all the
changes as methods operated on it and its components are still present.
However, when I write the Session object's contents to a log file, after
Session["MyObject"] has been set to "obj", the content of
Session["MyObject"] has lost changes that were made to MyObject's
components. Collections are reset to a previous state and component
objects may also have lost their updates. What is going on? If I run the
application with "In Process" session state the updates remain after
placing the top level object into session -- they only disappear when
running with "out of process" session state.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,529
Members
45,001
Latest member
Kendra00E1

Latest Threads

Top