Circular links and WCF

I created my POCO objects using the POCO Generator, I have more than 150+ tables in my database. I share POCO objects at all levels of the application, including the client. I have disabled LazyLoading and ProxyCreation in my context. I use WCF on top of my data access and business layer.

Now, when I return the poco object to my client, I get the error message: "The main connection was closed" I turned on WCF tracing and found the exact error: Contains loops and cannot be serialized if link tracking is disabled.

I looked at the MSDN and found solutions such as setting IsReference = true in the DataContract atttribute method, but I do not decorate my POCO DataContracts classes, and I believe that this is not necessary. I will not call it as POCO if I decorate the class with the DataContract attribute

Then I found solutions like applying the custom attribute [CyclicReferenceAware] on top of my ServiceContracts.That worked, but I wanted this question to be asked by the community to find out how other people manage it, and why Microsoft did not provide built-in support for calculating circular references when serializing POCO classes

+6
entity entity-framework wcf ado.net-entity-data-model
source share
3 answers

You already mentioned the approach, but I use this attribute

public class ReferencePreservingDataContractFormatAttribute : Attribute, IOperationBehavior { #region IOperationBehavior Members public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters) { } public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy) { IOperationBehavior innerBehavior = new ReferencePreservingDataContractSerializerOperationBehavior(description); innerBehavior.ApplyClientBehavior(description, proxy); } public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch) { IOperationBehavior innerBehavior = new ReferencePreservingDataContractSerializerOperationBehavior(description); innerBehavior.ApplyDispatchBehavior(description, dispatch); } public void Validate(OperationDescription description) { } #endregion } 

} ... and links to the operation on the Service, for example:

 [OperationContract] [ReferencePreservingDataContractFormat] IList<SomeObject> Search(string searchString); 

FYI - I would like to give a loan where it was, but did not write down where I initially saw the above approach.

Edit:

I believe the source code from this blog post .

+7
source share

I had the same problem and resolved it by excluding the navigation property back to the parent from the DataContract

 [DataContract] public partial class Parent { [Key] [DataMember] public virtual int ParentId { get; set; } [DataMember] public virtual string ParentName { get; set; } [DataMember] public virtual Child Child { get; set; } } [DataContract] public partial class Child { [Key] [DataMember] public virtual int ChildId { get; set; } [DataMember] public virtual string ChildName { get; set; } public virtual List<Parent> Parents {get; set;} } 
0
source share

I use the following calls to smooth EntityFramwork POCO entities before returning from the WCF service. It will crop the round children object based on the maxLevel value.

  /// <summary> /// Flattern one custom POCO entity. /// Work for resolve the circular reference issues in Entity Framework Code First POCO entity. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="entity"></param> /// <param name="maxLevel"></param> /// <param name="currLevel"></param> /// <returns></returns> public static T EntityFlatten<T>(this T entity, int maxLevel = 1, int currLevel = 1) where T : class { if (entity != null) { var myType = entity.GetType(); var myAssembly = myType.Assembly; var props = myType.GetProperties(); if (props != null) { // Walk through all properties defined in the POCO entity. foreach (var prop in props) { Type typeOfProp = prop.PropertyType; // // If the type is from my assembly == custom type // include it, but flatten its properties. // It is one custom POCO entity. // if (typeOfProp.Assembly == myAssembly) { if (currLevel < maxLevel) { prop.SetValue(entity, EntityFlatten(prop.GetValue(entity, null), maxLevel, currLevel+1)); } else { prop.SetValue(entity, null); } } else { //It should be POCO collection property if (typeOfProp.Namespace == "System.Collections.Generic") { if (currLevel < maxLevel) { var originalList = prop.GetValue(entity, null) as IList; if (originalList != null && originalList.Count>0) { for (int i=0; i<originalList.Count;i++) { var item = originalList[i].EntityFlatten(maxLevel, currLevel); originalList[i] = item; i++; } prop.SetValue(entity, originalList); } } else { prop.SetValue(entity, null); } } } } } return entity; } else return null; } /// <summary> /// Flatten the POCO entities collection. /// Work for resolve the circular reference issues in Entity Framework Code First POCO entity. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="entities"></param> /// <param name="maxLevel"></param> /// <param name="currentLevel"></param> /// <returns></returns> public static IList<T> EntitiesFlatten<T>(this IList<T> entities, int maxLevel = 1, int currentLevel = 1) where T : class { if (entities != null) { var list = entities as IList<T>; for (int i = 0; i < list.Count; i++) { T entity = list[i]; entity = entity.EntityFlatten<T>(maxLevel, currentLevel); } return list; } else return null; } 
0
source share

All Articles