Blog from Saravanan Arumugam

Let us talk about Technologies

Category Archives: Entity Framework

Entity Object as Data Contracts in WCF service


I have come across an interesting issue recently while I used Entity Objects in WCF. Before explaining the actual issue, let me explain a few concepts of serialization.

Entity Object vs. WCF

Entity objects are designed so rich, so that if it is chosen to be used in WCF, WCF would not require additional classes to serve as Data Contracts because the entity objects are usually decorated with the following attributes.

    [EdmEntityTypeAttribute(NamespaceName = "IntradoModel", Name = "ICRecord")]
    [Serializable()]
    [DataContractAttribute(IsReference = true)]
    public partial class ICRecord : EntityObject

EdmEntityTypeAttribute links the class to the conceptual model. It helps the Linq to Entity to recognize this type as a legal entity object. SerializableAttribute says that the object of this type can be serialized if needed. DataContractAttribute on the other hand also means that the the type is seriablizable but, by a special serializer – DataContractSerializer.

Note that the classes are partial, so just incase we need more members in the Data Contract, we can always write the partial class with additional members and extend it.

 

Some Concepts of Serialization

There are differences in the way the regular serializers (XmlSerializer, BinaryFormatter, SoapFormatter) and the DataContractSerializer chose the members to serialize. For example consider the following class.

public class SampleClass
{
    public int Number1 { get; set; }
    public int Number2 { get; set; }
    public int Number3 { get; set; }
 
    public int Sum { get; set; }
    public int Product { get; set; }
}

If we serialize an object of the above type, we would get something like below.

<SampleClass>
  <Number1>2</Number1>
  <Number2>2</Number2>
  <Number3>2</Number3>
 
  <Sum>6</Sum>
  <Product>8</Product>  
</SampleClass>

Serialization is usually a costly process, in terms of size, space, or transmission overhead. So its usual that you’d try to ignore some of the members during serialization without losing information. In our example, the information is carried through Number1, Number2, and Number3. But Sum and Product can always be calculated from the numbers at any point of time. So we can ignore them during serialization to save space, size and transmission overheads.

 

Opt-in vs. Opt-out method of serialization

The usual serializers, XmlSerializer, BinaryFormatter, and SoapFormatter works in the Opt-Out method. This means that all the members would be a part of the serialization unless you particularly ignore some. XmlIgnoreAttribute, NonSerializedAttribute, SoapIgnoreAttributes are the ones used to opt-out a member from getting serialized.

[Serializable]
public class SampleClass
{
    public int Number1 { get; set; }
    public int Number2 { get; set; }
    public int Number3 { get; set; }
 
    [NonSerialized]
    [XmlIgnore]
    [SoapIgnore]
    public int Sum { get; set; }
    
    [NonSerialized]
    [XmlIgnore]
    [SoapIgnore]
    public int Product { get; set; }
}

On the other hand DataContractSerializer, works in the Opt-in method. This means that during the serialization only the members marked with DataMemberAttribute would be serialized. Members without the attribute would be ignored during the serialization. Here we are opting-in what we want.

[Serializable]
[DataContract]
public class SampleClass
{
    [DataMember]
    public int Number1 { get; set; }
    [DataMember]
    public int Number2 { get; set; }
    [DataMember]
    public int Number3 { get; set; }
 
    [NonSerialized]
    [XmlIgnore]
    [SoapIgnore]
    public int Sum { get; set; }
 
    [NonSerialized]
    [XmlIgnore]
    [SoapIgnore]
    public int Product { get; set; }
}

 

Possible Issue in using Entity Objects as Data Contracts

I found the following exception when I tried using the Entity Objects as Data Contracts.

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

Usually an Entity Object contains the following structure. (We can find the structure of the entity model in Entities.Designer.cs)

    • Factory Method to create an object of its own type.
    • Primary Properties
    • Navigation Properties

Here factory method is not going to be part of the serialization, since its not a property. Primary and Navigation Properties would be part of serialization.

Primary properties provide all the information that you might need from the object. Navigation properties are to help the entity users for accessing the related tables/objects. So it doesn’t have the significance in serialization.

So Navigation Properties need not take part in serialization. XmlSerializer, and SoapFormatter would ignore them, but DataContractSerializer would not (I guess it’s a miss from Microsoft developers group or may be intentional). This is due to the attributes placed on these Navigation properties.

[XmlIgnoreAttribute()]
[SoapIgnoreAttribute()]
[DataMemberAttribute()]
[EdmRelationshipNavigationPropertyAttribute("MyModel", 
    "FK_ICRun_ICFile", 
    "ICFile")]
public ICFile ICFile
{
    get{

Reason for the exception

Usually the entity object uses the concept of Lazy Loading. In your code you’d be filling the object by using an object context, and close the context. But this would only fill the primary properties. Navigation properties would be filled only if you need them when you explicitly access them.

using (var context = new IntradoEntities())
{
    return context.ICFiles.Where(record =>
        (FileStatus)record.Status == FileStatus.Error).ToList();
}

When the DataContractSerializer encounters a navigation property, it would try to retrieve it during the runtime. But at the time of serialization Object Context would not be alive, so we end up with the exception.

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

Even the Eager Loading, the issue wouldn’t be over since there’s always a limit for the depth of objects during Soap transmission.

Solution

The solution is simple. Remove the DataMemberAttribute from the navigation properties.

To avoid any accidents of removing useful members from serialization, make sure you remove DataMemberAttribute only to those properties within the #region named as Navigation Properties.

I hope we’ll get a better Entity Framework version next time.

Enums in Entity framework


I had a need of using an Enum in one of the entities I created in Visual Studio 2010. Eventually I figured out that there’s no direct support to Enum in Entity framework 4.0. However there are workarounds to bring the Enum in place.

If we google, we can find out some of the workarounds to use the Enum.

Solution

Here’s a simple method I came up with to use the Enum, in an entity.

If we open Entities.Designer.cs file, we can find that the files are partials.

    [EdmEntityTypeAttribute(NamespaceName="MyModel", Name="ICFile")]
    [Serializable()]
    [DataContractAttribute(IsReference=true)]
    public partial class ICFile : EntityObject

Step 1: To support enum, create an enum.

    public enum FileStatus
    {         InProgress = 0,         Error = 1,         Completed = 2
    }

Step 2: In the namespace of the Entities, create a partial class as the entity you want to expand.

    public partial class ICFile
    {                 [DataMemberAttribute()]         public FileStatus FileStatus         {             get
            {                 return (FileStatus)this.Status;             }             set
            {                 this.Status = (int)value;             }         }     }

Step 3: Create a full property that’ll uses the existing property of the entity but wraps it with the enum we created as in the above example.

So from now on, the new property (FileStatus) would be available in the entity for any kind of statements we use.

context.AddToICFiles(     new ICFile
    {         FileName = FileName,         FileStatus = FileStatus.InProgress     });

However, this property wouldn’t be available/supported any linq statements. (Or perhaps I haven’t figured that out).

var fileEntry = (from entry in context.ICFiles
    where entry.FileName == FileName &&
        //Following statment is not supported by the linq to entity, 
        //since and Edm property has to be marked as EmdPropertyAttribute. 
        //But FileStatus is not marked with an attribute.
        //entry.FileStatus == FileStatus.InProgress && 
 
        //This would work well.
        entry.Status == (int)FileStatus.InProgress
    select entry).First();

The code above explains what’s not supported and how to solve it.