This question is locked. New answers and comments are not allowed.
Hello,
I'm having a problem with Lazy/Eager Loading and Serialization. I'll try to explain the issue conceptually first and then provide some code to backup my findings.
First, for what I understand, when I have a relationship like Entity1 -> Entity2 in a property like Entity1.Two, the ORM engine will replace the reference in Entity1 with an object of its own which will handle lazy loading behavior. After the initial load, when I first access a field in Entity2 (say Entity1.Two.Name) the engine will load data and fill the Entity2 actual object.
Second, I understand also that if I try to serialize an Entity1 object, it won't go automatically filling it's dependant relationships and the non-loaded lazy-load relationships will end up as null on the serialization.
The issue I'm facing it seems that this Telerik-LazyLoading-Object is not serializable and not even using a FetchStrategy to force an eager load seem to fix it.
So, talking code now, I have a very simple entity setup (to keep the example straightforward Entity1 has some simple binary serialization embedded):
And also a Web Forms project for testing. The project consists of a single page with a single button. When we first load the page, we load an Entity1 which already exists with a Strategy which eager loads its Entity2 reference. We serialize Entity1 and store it in the viewstate. Later, when we click the button we land on the other branch and try to rebuild Entity1 by deserializing it.
What I expected was that since I eager loaded Entity2 reference, the serialization process wouldn't have a problem to include the reference. But it seems it's not the case.
As it so happens, if I insert a breakpoint right after the entity1-fetching-line and inspect object e1 (acessing property "Two" and forcing the actual load) the serialization would run just fine and when I deserialize it, Entity2 would be present. If I don't inspect e1, Entity2 will end up null after deserializing. This behavior seem to be inaltered by the presence or not of the FetchStrategy, tough I have some strong evidence that the eager loading is acting ok. It just seems that despite eager loading, the Entity2 reference is still replaced by some sort of proxy which fails to serialize if I don't access it first.
Is it by design? Or have I misinterpreted the engine and I'm screwing up somewhere?
I'm having a problem with Lazy/Eager Loading and Serialization. I'll try to explain the issue conceptually first and then provide some code to backup my findings.
First, for what I understand, when I have a relationship like Entity1 -> Entity2 in a property like Entity1.Two, the ORM engine will replace the reference in Entity1 with an object of its own which will handle lazy loading behavior. After the initial load, when I first access a field in Entity2 (say Entity1.Two.Name) the engine will load data and fill the Entity2 actual object.
Second, I understand also that if I try to serialize an Entity1 object, it won't go automatically filling it's dependant relationships and the non-loaded lazy-load relationships will end up as null on the serialization.
The issue I'm facing it seems that this Telerik-LazyLoading-Object is not serializable and not even using a FetchStrategy to force an eager load seem to fix it.
So, talking code now, I have a very simple entity setup (to keep the example straightforward Entity1 has some simple binary serialization embedded):
[Serializable]
public
class
Entity1
{
public
Int32 Id {
get
;
set
; }
public
String Name {
get
;
set
; }
public
Int32 TwoId {
get
;
set
; }
public
Entity2 Two {
get
;
set
; }
public
byte
[] GetSerialized()
{
using
(System.IO.MemoryStream aStream =
new
System.IO.MemoryStream())
{
BinaryFormatter aSerializer =
new
BinaryFormatter();
aSerializer.Serialize(aStream,
this
);
aStream.Position = 0;
return
aStream.ToArray();
}
}
public
static
Entity1 LoadFromSerializedString(
byte
[] serializedString)
{
using
(System.IO.MemoryStream aStream =
new
System.IO.MemoryStream(serializedString))
{
BinaryFormatter aDeserializer =
new
BinaryFormatter();
aStream.Position = 0;
Entity1 e1 = (Entity1)aDeserializer.Deserialize(aStream);
return
e1;
}
}
}
[Serializable]
public
class
Entity2
{
public
Int32 Id {
get
;
set
; }
public
String Name {
get
;
set
; }
public
IList<Entity1> Ones {
get
;
set
; }
}
And also a Web Forms project for testing. The project consists of a single page with a single button. When we first load the page, we load an Entity1 which already exists with a Strategy which eager loads its Entity2 reference. We serialize Entity1 and store it in the viewstate. Later, when we click the button we land on the other branch and try to rebuild Entity1 by deserializing it.
public
partial
class
Index : System.Web.UI.Page
{
protected
void
Page_Load(
object
sender, EventArgs e)
{
if
(!Page.IsPostBack)
{
Domain.PresenterContext aContext =
new
Domain.PresenterContext();
Telerik.OpenAccess.FetchOptimization.FetchStrategy aStrategy =
new
OpenAccess.FetchOptimization.FetchStrategy();
aStrategy.LoadWith<Domain.Entity1>(x => x.Two);
aStrategy.MaxFetchDepth = 10;
aStrategy.MaxResultsLimit = 100;
aContext.FetchStrategy = aStrategy;
Domain.Entity1 e1 = aContext.Ones.Single(x => x.Name ==
"1_2"
);
byte
[] serialized = e1.GetSerialized();
ViewState[
"e1"
] = serialized;
}
else
{
byte
[] serialized = (
byte
[])ViewState[
"e1"
];
Domain.Entity1 e1 = Domain.Entity1.LoadFromSerializedString(serialized);
}
}
protected
void
Button1_Click(
object
sender, EventArgs e)
{
}
}
What I expected was that since I eager loaded Entity2 reference, the serialization process wouldn't have a problem to include the reference. But it seems it's not the case.
As it so happens, if I insert a breakpoint right after the entity1-fetching-line and inspect object e1 (acessing property "Two" and forcing the actual load) the serialization would run just fine and when I deserialize it, Entity2 would be present. If I don't inspect e1, Entity2 will end up null after deserializing. This behavior seem to be inaltered by the presence or not of the FetchStrategy, tough I have some strong evidence that the eager loading is acting ok. It just seems that despite eager loading, the Entity2 reference is still replaced by some sort of proxy which fails to serialize if I don't access it first.
Is it by design? Or have I misinterpreted the engine and I'm screwing up somewhere?