views:

25

answers:

1

Hi

I've been looking around for this for quite some time and cannot seem to get anywhere. I need to find a way to accomplisht the following two tasks, based on a .Net Entity object:

  1. Create an XML file that contains the data in this entities, complete, with cascading nodes (representing foreign key relationships, basically). I've considered copying the data to a DataSet and then doing a WriteXml() on it, but this seems like an overkill. Entities must have a more direct way. Note, though, that I'm not trying to serialize the object. I just need the data in a simple XML file.
  2. Related to point 1, I need to also save an XSD representing the schema of this Entity, to go hand in hand with the XML mentioned above. Again, going through a DataSet and then WriteXmlSchema() is an option, but feels like overkill.

Is there anything in the Entity universe that can help do this in a simple way ?

Thx.

+1  A: 

I think a combination of XML serialization and schema inference is probably all that you need.

The XmlSerializer should be good enough to generate the XML file that you're looking for. You really don't need to do anything besides pass in the stream or stream writer, and the instance of the root-level entity. The actual code for XML serialization is 2 lines:

// for example:
public static void Serialize<T> (T data, TextWriter writer)
{
    var xs = new XmlSerializer(typeof(T))
    xs.Serialize(writer, data);  // write out the xml to the stream writer...
}

I'm not sure why you want to avoid XML serialization.

In order to save the XSD relative to the set of entities, you can infer the schema from the generated XML. Schema inference is done by using the XmlSchemaInference class in conjunction with XmlSchemaSet.

I usually create a small schema inference utility for myself wherever I go, it looks like this:

class Program
{
    static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine("Nothing to do.");
            return;
        }

        // first arg should contain the path to xml else error
        Console.WriteLine("Inferring schema of: {0}", args[0]);

        // default output should be xml name part + .xsd
        InferSchema(args[0]);
    }

    static void InferSchema(string fileName)
    {
        XmlWriter writer = null;
        XmlSchemaInference infer = new XmlSchemaInference();
        XmlSchemaSet sc = new XmlSchemaSet();

        string outputXsd = fileName.Replace(".xml", ".xsd");
        sc = infer.InferSchema(new XmlTextReader(fileName));

        using (writer = 
            XmlWriter.Create(new StreamWriter(outputXsd)))
        {
            foreach(XmlSchema schema in sc.Schemas())
            {
                schema.Write(writer);
                Console.WriteLine(">> found schema - generated to {0}", 
                    outputXsd);
            }
        }
    }
}

It doesn't get any simpler than that.

code4life
Thx for the quick answer. Re serialization - not sure why I'm avoiding it, to be honest. I had the impression that serializing the file would give me more info about the class than just the structure or data. Upon rethinking it, you might be right. Need mroe coffee. As for XSD - I'll definitely try it out. Looks like this might work. Thx a bunch!
David Catriel
Well, I started testing this, and am running into strange results. I got the serialization to work, but am getting an XML file with nothing more than a head tag describing the main table in the entity. No data. I ensured lazy loading is off, and even "watched" the retrieved object to ensure it has data, but no luck. I'll keep on digging. Any ideas ?
David Catriel
Minor update - serializer was not doing much because the objet type I had defined was of type var instead of the actual EntityType. My issue now is that only data from the top level EntityType is being serialized; I get nothing from the subtables, even though I'm referencing their navigation properties with .Include() on the Linq query. Wewy wewy stwange.
David Catriel
Ok, huge issue with XML serialization - it DOES NOT handle related objects. Only binary and WCF serialization does this: "When you use binary serialization and WCF data contract serialization, if the object being serialized has related objects in the object graph, those objects are also serialized. XML serialization does not serialize related objects.". See "http://msdn.microsoft.com/en-us/library/bb738446.aspx".
David Catriel
Ok, I think I found it. Simple XML serialization does not work as it will NOT contain the referenced properties (i.e. subtables). The DataContractSerializer does work, though. Found a good article on it here: http://www.riggshill.com/home/taxonomy/term/37. Thx for getting me on the right path, code4life !
David Catriel