Entity ReadXml using Context?

Posts   
 
    
Koubessus
User
Posts: 28
Joined: 30-Dec-2004
# Posted on: 30-Sep-2008 21:02:35   

Hi.

I am trying to find some easy way to offer graph rollback functionality and one possible way which offers itself is XML serialization/deserialization.

But I would also like to maintain current references in the application so I thought it would be usefull if I could just read values from XML file into the existing entities.

Adding Context to the entity seems like a way to go except the context is not used during deserialization. If I read the same XML into the same entity twice, I get unique instances in the Context but all entities are added to the collection twice:


Context context = new Context(true);
SchemaEntity test = new SchemaEntity();
context.Add(test);

XmlReader reader = XmlReader.Create("e:\\temp\\pilot\\data\\subject.xml");
reader.MoveToContent();
test.ReadXml(reader, XmlFormatAspect.Compact25);
reader.Close();

int count = test.SchemaFields.Count; // = 3

XmlReader reader = XmlReader.Create("e:\\temp\\pilot\\data\\subject.xml");
reader.MoveToContent();
test.ReadXml(reader, XmlFormatAspect.Compact25);
reader.Close();

int count2 = test.SchemaFields.Count; // = 6

int totalCount = context.GetAllTypes().Count; // = 7

Am I missing something obvious or it's just a wrong way to go?

Also, while I was at it, I was playing with ObjectGraphUtils class. It seems like a really usefull one, but for the love of God I couldn't find a purpose of ProduceAdjacencyLists method. flushed

I am using LLBLGen v. 2.5.07.1219

Thanks

Jakub

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 01-Oct-2008 11:49:42   

The serialized entity, was it a new one or a saved one(fetched from the database) ?

Koubessus
User
Posts: 28
Joined: 30-Dec-2004
# Posted on: 01-Oct-2008 12:42:44   

Walaa wrote:

The serialized entity, was it a new one or a saved one(fetched from the database) ?

If was a new one - constructed in-memory, not stored yet.

Primary keys of SchemaEntity and SchemaFieldEntity are of type uniqueidentifier with default value set to (newid()), but with RowGuid = false.

I am using SQL Server 2005.

Koubessus
User
Posts: 28
Joined: 30-Dec-2004
# Posted on: 01-Oct-2008 13:30:08   

I've changed my test. Now I work with fetched fields from database.

But the result remains the same. This is the result (from Immediate window):


? test.SchemaFields[3] == test.SchemaFields[0]
false
? test.SchemaFields[3].ObjectID == test.SchemaFields[0].ObjectID
true

BTW: is it possible to mark entity and its fields to Fetched state without actually fetching it?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 02-Oct-2008 11:15:52   

To which level do you want to roll back your graph exactly? Do you want to roll back values inside an entity or do you want to rollback references to entities as well? (i.e. user added Order entity to customer.Orders collection, you roll back, so the order is removed from the customer.Orders collection)

the 'easiest' way is by using binary serialization with fast serialization enabled. You'd basicly do this: - at the point to which you want to rollback, you serialize your graph to a memory stream, grab the byte array. That's your cache. - do your thing with the data - you want to rollback, deserialize the byte array.

You'll get different instances. The problem is: if you have added a new entity to a collection, how is that entity removed during the rollback? simple_smile That's not possible, unless the container (collection) is rebuilt, i.e. new instances.

Rolling back values inside an entity is done with SaveFields and RollbackFields.

Frans Bouma | Lead developer LLBLGen Pro
Koubessus
User
Posts: 28
Joined: 30-Dec-2004
# Posted on: 02-Oct-2008 12:39:51   

Well, I would really like to roll back the whole graph.

I know about the SaveFields and RollbackFields methods, unfortunately those don't solve add/remove related entity situation. And using deserialization won’t solve my requirement for a single in-memory instance. disappointed

Just to make sure I understand it correctly – if I use fast binary (de)serialization, I will recreate the complete graph as it was at the time of serialization (including all collections) but using new instances of all objects? Hmm. I wonder what would that mean for GUI data binding… And the fact, that sometimes I would like to rollback just a part of the graph as some parts of the graph may belong to a different logical group of entities.

Did anyone try to create an “Undo” functionality for entity graph?

I’m thinking about sharing some observer in my logical part of graph (similar to ActiveContext) which would handle all property changed and related entity set/unset events and then allow me to revert them back. Do you think this is worth trying?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 02-Oct-2008 16:30:25   

Undo/redo is something we researched ourselves for v3's designer, as we needed full undo/redo of object graphs and object properties. We came up with a solution, but it's based on Func/Action delegates of .NET 3.5, and based on a graph class, not something you'll find in the runtime lib at the moment (the code of our graph etc. will be released as a separate library as open source later this year)

Creating undo facilities is pretty complex if you want to do it from one central point. So what you actually should do is indeed use observers and check when some object changes, like a collection. If that happens, store the change: field values through the RollbackFields, and collection contents by removing an entity (or adding it again when it was removed!).

I'm not sure if this will cover all the inner details of all elements in a graph, and it can be pretty complex. What I'd do instead is simply rebind the data, which IMHO is easier to do. (as in: the user either cancels a long series of actions, or accepts them, there's no undo /redo of a single action).

Frans Bouma | Lead developer LLBLGen Pro
Koubessus
User
Posts: 28
Joined: 30-Dec-2004
# Posted on: 02-Oct-2008 17:18:53   

Well, thanks for the effort. Really, I mean it! wink

We are using LLBLGen entities in a non-standard way ( again disappointed ) and binding to GUI is not the main issue here. I am trying to mainain a potentially large entity graph in memory and one form edits only small part of this graph.

Creating new instances would break my entity references outside of the form.

Hmm. Maybe I could store the entities in embedded database and just refetch them using Context. Would that keep my references in place?

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 02-Oct-2008 17:47:44   

Hmm. Maybe I could store the entities in embedded database and just refetch them using Context. Would that keep my references in place?

Yes. I was going to suggest just the same approach, most of the time I do a re-fetch for undo simple_smile

Koubessus
User
Posts: 28
Joined: 30-Dec-2004
# Posted on: 03-Oct-2008 13:07:18   

Ok. I will see whether it is possible for me go this way. In any case - I'll let you know, if I succeed in some way simple_smile

Thanks a lot.

rdhatch
User
Posts: 198
Joined: 03-Nov-2007
# Posted on: 17-Jan-2009 18:05:54   

Koubessus -

Were you able to find a solution?

I also need several OK/Cancels without going back to SQL Server. (multiple edit forms)

Please let me know how you did! Thanks!

Ryan D. Hatch