In the question titled "Serializing a persistent object", I asked how to serialize an object. The sample code provided doesn't seem to work, in the sense that it doesn't actually serialize the object into a form that can be communicated to another process (which of course is the whole point of serialization). The resulting stream contains no data; I speculate that it contains a reference to a cached in-memory object. In any case, as far as I can tell, the data in the stream is unusable outside the context of the process that created it.

  1. Using the sample code in "Serializing a persistent object", have I perhaps omitted a step that is necessary in order to create a fully serialized object? Or have I made some other error or misunderstood something?

  2. If the answers to 1. are negative, how can I serialize an Entity such that it can be communicated to another process (which is not going to have access to the database holding the original object)?

asked Nov 20 '14 at 10:46

TimB's gravatar image

TimB
7558

Hi TimB.

Once again. You have two sides - server application (or service), which has access to database (Server database) and uses DO; client application (WPF, WinForms,Windows service, Asp.net application, whatever) which has no access to server database. Does client application have it's own database? Do they use one DO types model? Or maybe client application just deserialize XML to some object with same structure as Entity on server side and do not need DataObjects at all?

(Nov 21 '14 at 06:39) Alexey Kulakov Alexey%20Kulakov's gravatar image

The clients in my case are POS devices that have limited capabilities. They might have SQLite for certain functions, but the databases that contain the information needed for processing transactions reside on store and corporate servers. My goal is to have a single unified object model across all layers, even though some layers will not use certain parts of the model. Using DO, we can build the domain for Oracle on the corporate servers, and MySQL on the store servers. In theory, we could even build it for SQLite on the POS systems, but the data would generally not be available (continued)

(Nov 21 '14 at 13:03) TimB TimB's gravatar image

at this level. There is a message queue system that supports communication across servers. Here's an example. A customer wishes to return an item to store A which was purchased at store B earlier in the day. The transaction might not have reached the corporate server yet. Store servers have no knowledge of each other, but they do know about message queue channels. Store A requests the complete transaction record using a message, and store B responds. It is the content of that response message that is the key to my problem. Store B has retrieved a class Transaction : Entity (continued)

(Nov 21 '14 at 13:12) TimB TimB's gravatar image

record from its database (with aggregated details such as item records and tender records). That record needs to be communicated to the store A server, and from there to the POS system where the transaction is being processed. What I would like to do is (XML) serialize the record at store B, then place it in the message for ultimate delivery to the POS system, where it would be deserialized into either a Transaction : Entity object (that would be most convenient), or an object of a non-Entity class generated automatically from the same source code. The schema is fairly complex. (continued)

(Nov 21 '14 at 13:21) TimB TimB's gravatar image

What I'm trying to avoid is having to maintain parallel Entity and DTO classes. If that's not possible using DO, perhaps it is at least possible to generate the DTO classes from the same codebase (I think I know how to do this). I could even maintain the DO model on the POS systems in SQLite if that would facilitate object transfer. But so far, I've been unable to successfully serialize the Entity objects on the server as a first step. Do you see a way to make this work?

(Nov 21 '14 at 13:34) TimB TimB's gravatar image

2 Answers:

Hi TimB

This explanation is more useful.

First of all, in example in "Serializing a persistent object" question I used SerializationKind.ByReference. When SerializationKind.ByReference used then DO try to check that all references. So DO make a query to database on deserialization. I think it's my bad. Did you try to use SerializationKind.ByValue?

About XML serialization. I know that XmlSertializer requires constructor without parameters for type. Entity contains constructor without parameters but this constructor initializes entity with new key. And you can't change it after initialization. Build-in deserialization uses special constructor of Entity.

Also, want to say:

1) You said that some Entities may do not use in some layers. So why do you want to create useless tables. Even if your model would be different in different layers, you must keep in synchronized state. I mean that DO have type identifier for each type and it can be different in different domains. Current type identifier defined by sequence of values and already defined type identifiers (takes form stored metadata). You can define identifier manually, but then you must take care about it.

2) POS layer don't need DO at all. I think, building of domain on POSs just for deserialize Entity is bad idea.

3) DO can lazily resolve all the references, when serializer will traverse the graph and in some cases you'll see the whole graph serialized.

So I think that using of DTO is good for you.

answered Nov 26 '14 at 06:21

Alexey%20Kulakov's gravatar image

Alexey Kulakov
60715

I can't find any documentation on SerializationContext/Kind, so I don't know if I'm using it correctly. When I serialize ByReference, as I described earlier, I get a stream that appears to consist of nothing but internal pointers, and no actual data. I tried ByValue as you suggested, but formatter.Serialize throws this exception:

"Type 'Xtensive.Orm.EntitySet`1[[DOSerialization.Child, DOSerialization, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' in Assembly 'Xtensive.Orm, Version=5.0.0.0, Culture=neutral, PublicKeyToken=93a6c53d77a5296c' is not marked as serializable."

Here are the two classes I'm using for testing:

[Serializable] [HierarchyRoot] public class Parent : Entity { public Parent() { } [Field, Key] public int Id { get; private set; } [Field(Length = 20)] public string Name { get; set; } [Field] public EntitySet<child> Children { get; private set; } }

[Serializable] [HierarchyRoot] public class Child : Entity { public Child(Parent parent) { Parent = parent; } [Field, Key] public long Id { get; private set; } [Field(Length = 20)] public string Name { get; set; } [Field] [Association(PairTo = "Children", OnTargetRemove = OnRemoveAction.Cascade)] public Parent Parent { get; private set; } }

You make some interesting points with your additional comments.

  1. Using DO, our goal is to define an "enterprise data model" in code. (If we were using some other tool, we would perhaps take a different approach, but we want to see what DO can do.) We can compile for different platforms, but that doesn't mean that each platform/layer needs to register every class with DomainConfiguration.Types.Register. In other words, each database would only have the tables that are actually needed at that level. I don't know what the issues are with type identifiers, but we are trying to solve one problem at a time; I hope there will be a solution when we get to that point.
  2. I agree that adding DO to the POS layer just to support deserialization is not a good idea. However, the POS layer will require DO for other purposes. Specifically, a POS register must be able to complete transactions even when there is no network connection. Transaction data must be stored locally until such time as it can be transmitted. The system we are trying to replace stores the transactions in a flat file. The new system will likely store them in a SQLite (or equivalent) database. So, the POS systems will use the Transaction portion of the larger data model to store data locally, but only needs to understand other classes, such as Customer, which are retrieved from other systems via messages and displayed, but never stored.
  3. Our object graphs will be acyclic, so if I understand your point, I don't think it will be a problem.
  4. If we can't serialize Entity objects, then DTO may be the solution. My concern is that our Transaction model, for example, has 27 classes. I need some mechanism to automatically generate and synchronize the DTO classes using the Entity classes as input. Automatically generated code should be able to load a DTO object from an Entity object, and vice versa. I think I can do this using #if, substitute base classes, and a separate project for the DTO classes; and a reflection-based cross-loader to move data between Entity and DTO objects.

I haven't given up yet on DO, but this is taking more effort than I had hoped. Perhaps there's a different approach I should try?

answered Nov 26 '14 at 11:57

TimB's gravatar image

TimB
7558

May I ask you to use preformatted text for classes or another code next time? It makes you code easier to read. In the answer textbox you have special button called preformated text. Or you can write <pre> and <code> tags manually in comment and answer textboxes both.

(Nov 27 '14 at 01:18) Alexey Kulakov Alexey%20Kulakov's gravatar image

1) I prefer to predict any problems and tell users about them. 2) Ok than. 4) I know few projects that uses DTOs. They have large model too. It's simpler for them to use serialization of DTOs then to use DO serialization or any complex mappers for serialization.

I thing I'll try to prepare some example project if I'll have enough time on this week, maybe at this weekend.

(Nov 27 '14 at 01:48) Alexey Kulakov Alexey%20Kulakov's gravatar image
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

powered by OSQA