开发者

Entity Framework and the XmlIgnoreAttribute

Say you have a one to one relationship in your entity model. The code generator will decorate it with the following attributes:

[global::System.Xml.Serialization.XmlIgnoreAttribute()]
[global::System.Xml.Serialization.SoapIgnoreAttribute()]
public RelatedObject Relationship { get {...} set {...} }

I want to serialize my parent object together with all its properties for which data has been loaded through an XML web service. Obviously, these related properties do not get serialized because of these attributes.

So for my purposes I just want to remove these "don't serialize me" attributes. I can do a find and replace in the designer code, but any modifications I make in the designer will put these attributes back in.

In my query I'm .Include()ing and explicitly loading only the child objects that I require for serialization. So I will make sure there are no circularities in my query. Some of the child properties are not required, so I won't Include() them, so they won't be serialized.

Else how do I achieve what I want to do? Make a separate call from my application for each child object? Say I'm returning hundreds of parent objects; I'd have to make hundreds of separate calls to get each child too.

How do I permanently get rid of these attributes?

V开发者_StackOverflowS 2008 / EF 3.5.


Just don't do it. It's that simple.

You state on your post that you want to serialize the parent of your object, right?

Now let's see what happens when you do something like that...

  1. The serializer starts converting your object and it's properties
  2. When it finds the parent of your object, it starts serializing it
  3. While serializing the parent if finds the child object that it was serializing and goes back to 1.

And it will never get out, without some encouragement.

So those attributes are there for a good reason.


Here is a little known fact... Entity Framework + Web Services = :'(

There are three(3) approaches that can be taken to solve your problem (namely the XML graph serialization problem... or the lack of it).

I will list each approach in order of least development time and complexity of implementation required ["Bang-For-Buck"] vs. scalability, maintainability and performance ["Future Proofing"].

  1. Create POCO classes for each Entity for projection when sending over the wire. This is the easiest (and monotonous) approach but will solve your problem. I have included a sample at the end.

  2. Use WCF to relay your data. Entity Framework and WCF are like 'brothers from a different mother'. They were designed to work together but share their differences. You will notice that all EF generated Entity Objects are inherently [DataConctract] with all fields being [DataMember]. This makes use of the WCF DataContract Serializer with handles graphs very efficiently and maintains object reference even after deserialization. WCF DataContract Serializer is also proven to be 10% quicker than your default XML Serializer.

  3. Use EF 4.0 Self Tracking Entities (STE). This is still very new but it is workable. In Visual Studio 2010 you are given an option to generate Self Tracking Entities which are designed for N-Tier and SOA. The best thing about STE is the usage of T4 Transformed Text templates to generate the code. The classes generated by T4 is clean and very malleable, giving you plenty of room to insert your logic and validation. Here is a link to STE tutorial to get your started.

Best of luck and I hope you find the best approach for you.

POCO example.

public class CustomerPOCO
{
    public int ID { get; set; }
    public string Name { get; set; }
    public List<SubLocationPOCO> SubLocations { get; set; }
    // ...

    #region Ctors

    public CustomerPOCO() { }

    public CustomerPOCO(Customer customer)
    {
        // Inits
        if (customer.SubLocations != null)
            SubLocations = customer.SubLocations.Select(sl => new SubLocationPOCO(sl)).ToList();
    }

    #endregion

}


public class SubLocationPOCO
{
    public int ID { get; set; }
    public string Name { get; set; }

    #region Ctors

    public SubLocationPOCO() { }

    public SubLocationPOCO(SubLocation subLocation)
    {
        // Inits
    }

    #endregion

}

And your [WebMethod] is something like this.

[WebMethod]
public CustomerPOCO GetCustomerByID(int customerID)
{
    using (var context = new CustomerContext())
    {
        var customer = (from customer in context.Customers.Include("SubLocations")
                        where customer.ID == customerID
                        select new CustomerPOCO(customer)).FirstOrDefault();

        return customer;
    }
}


Paulo is right (+1) but he didn't tell you how to fix the problem. Because XML serialization is a legitimate use case, even if serializing entities is the wrong way to do it.

Project onto anonymous types, and serialize that. E.g., to serialize to JSON, I do:

var q = from e in Context.MyEntities
        where // ...
        select new
        {
            Id = e.Id,
            Children = from c in e.Children
                       select new 
                       {
                           Id = c.Id,
                           // etc.
                       },
            // etc.
        };
return Json(q);

This guarantees no circular references, etc., and it works.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜