c# - otra - llamar funcion php desde otro php
El objeto complejo no volverá cuando use la sintaxis ''include'' en WCF con Entity Version 6 (1)
Bien, este me ha dejado perplejo ya que acabo de ver que mi cliente básicamente se desconecta y termina cuando devuelve un objeto con ''incluir''. Sin embargo, funciona bien sin eso a través de un SERVICIO WCF. El problema es que realmente quiero que esos objetos conectados se configuren a través de la navegación.
Básicamente, el código es un retorno de objeto complejo:
public teCIF getCif(int aCifId)
{
using (CIFContainer context = GetCifContext())
{
var thing = context.teCIFs
.Include("Product_TYPE")
.FirstOrDefault(i => i.CIF_ID == aCifId);
return thing;
}
}
Ahora lo extraño es que esto funcionará SIMPLEMENTE BIEN cuando comento la declaración de inclusión. Es como si el tipo complejo que se envía por el servicio WCF no le gusta la instrucción include y simplemente dice: "no, no va a hacer eso".
Como referencia, mi Objeto complejo ya he pirateado bastante, ya que es un objeto generado por T4 de una base de datos (abreviado):
[Serializable]
public partial class teCIF
{
public int CIF_ID { get; set; }
public string CUSTOMER_NAME { get; set; }
public string SITE_NAME { get; set; }
[System.Xml.Serialization.XmlIgnore]
public int PRODUCT_TYPE_ID { get; set; }
public virtual tlPRODUCT_TYPE Product_TYPE { get; set; }
}
Actualización para vincular el elemento copmplex:
[Serializable]
public partial class tlPRODUCT_TYPE
{
public tlPRODUCT_TYPE()
{
this.teCIFs = new HashSet<teCIF>();
}
[System.Xml.Serialization.XmlIgnore]
public int PRODUCT_TYPE_ID { get; set; }
public string VALUE { get; set; }
[System.Xml.Serialization.XmlIgnore]
public virtual ICollection<teCIF> teCIFs { get; set; }
}
He intentado eliminar atributos pero aún no me he equivocado con el tipo de "miembro de datos" que le gusta a WCF. Simplemente no entiendo por qué esto no funciona ya que he jurado que he hecho esto en el pasado Entity Version 4 con tipos complejos con propiedades de navegación relacionadas con otros tipos complejos.
Está bien, así que en realidad recibí ayuda de un amigo, pero pensé que esto podría surgir para otros, así que debería responder la pregunta, ya que puede ayudar a otra persona. Tuve que agregar un atributo personalizado para el que hago una clase que determina las referencias cíclicas. Básicamente, los punteros a la navegación se perdían de alguna manera al usar WCF, pero estaban bien cuando no estaban conectados a un servicio. Esto no es bueno ya que quiero que mi servicio aloje los métodos usando WCF, no solo las llamadas de los clientes directamente usando Entity V6.
[ServiceContract]
public interface ICifService
{
[OperationContract]
[CyclicReferencesAware(true)]
teCIF getCif(int aCifId);
}
La clase de implementación funciona así:
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Runtime.Serialization;
using System.Xml;
using System.Collections.Generic;
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Method)]
public class CyclicReferencesAwareAttribute : Attribute, IContractBehavior, IOperationBehavior
{
private readonly bool _on = true;
public CyclicReferencesAwareAttribute(bool on)
{
_on = on;
}
public bool On
{
get { return _on; }
}
#region IOperationBehavior Members
void IOperationBehavior.AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
void IOperationBehavior.ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation)
{
CyclicReferencesAwareContractBehavior.ReplaceDataContractSerializerOperationBehavior(operationDescription, On);
}
void IOperationBehavior.ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
{
CyclicReferencesAwareContractBehavior.ReplaceDataContractSerializerOperationBehavior(operationDescription, On);
}
void IOperationBehavior.Validate(OperationDescription operationDescription)
{
}
#endregion
#region IContractBehavior Members
void IContractBehavior.AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
void IContractBehavior.ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
CyclicReferencesAwareContractBehavior.ReplaceDataContractSerializerOperationBehaviors(contractDescription, On);
}
void IContractBehavior.ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime)
{
CyclicReferencesAwareContractBehavior.ReplaceDataContractSerializerOperationBehaviors(contractDescription, On);
}
void IContractBehavior.Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
#endregion
}
public class CyclicReferencesAwareContractBehavior : IContractBehavior
{
private const int MaxItemsInObjectGraph = 2147483647;
private const bool IgnoreExtensionDataObject = false;
private bool _on;
public CyclicReferencesAwareContractBehavior(bool on)
{
_on = on;
}
#region IContractBehavior Members
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
ReplaceDataContractSerializerOperationBehaviors(contractDescription, _on);
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime)
{
ReplaceDataContractSerializerOperationBehaviors(contractDescription, _on);
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
internal static void ReplaceDataContractSerializerOperationBehaviors(ContractDescription contractDescription, bool on)
{
foreach (var operation in contractDescription.Operations)
{
ReplaceDataContractSerializerOperationBehavior(operation, on);
}
}
internal static void ReplaceDataContractSerializerOperationBehavior(OperationDescription operation, bool on)
{
if (operation.Behaviors.Remove(typeof(DataContractSerializerOperationBehavior)) || operation.Behaviors.Remove(typeof(ApplyCyclicDataContractSerializerOperationBehavior)))
{
operation.Behaviors.Add(new ApplyCyclicDataContractSerializerOperationBehavior(operation, MaxItemsInObjectGraph, IgnoreExtensionDataObject, on));
}
}
#endregion
}
internal class ApplyCyclicDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior
{
private readonly int _maxItemsInObjectGraph;
private readonly bool _ignoreExtensionDataObject;
private readonly bool _preserveObjectReferences;
public ApplyCyclicDataContractSerializerOperationBehavior(OperationDescription operationDescription, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences)
: base(operationDescription)
{
_maxItemsInObjectGraph = maxItemsInObjectGraph;
_ignoreExtensionDataObject = ignoreExtensionDataObject;
_preserveObjectReferences = preserveObjectReferences;
}
public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
{
return new DataContractSerializer(type, name, ns, knownTypes, _maxItemsInObjectGraph, _ignoreExtensionDataObject, _preserveObjectReferences, null /*dataContractSurrogate*/);
}
public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
{
return new DataContractSerializer(type, name, ns, knownTypes, _maxItemsInObjectGraph, _ignoreExtensionDataObject, _preserveObjectReferences, null /*dataContractSurrogate*/);
}
}
Una vez que aplique este atributo a cualquier operación en mi interfaz para mi servicio, funcionó bien para cualquier tipo complejo.