使用'include'时,复杂对象won'在WCF与实体版本6中的语法

本文关键字:版本 实体 语法 WCF won include 复杂 使用 对象 | 更新日期: 2023-09-27 18:14:23

好的,所以这个让我难住了,因为我只是看到我的客户端基本上断开连接并在返回带有'include'的对象时终止。但是,如果没有跨WCF服务,它就可以正常工作。问题是我真的希望通过导航设置这些连接的对象。

基本上代码是一个复杂的对象返回:

public teCIF getCif(int aCifId)
        {
            using (CIFContainer context = GetCifContext())
            {
                var thing = context.teCIFs
                    .Include("Product_TYPE")
                    .FirstOrDefault(i => i.CIF_ID == aCifId);
                return thing;
            }
        }

现在奇怪的是,当我注释掉include语句时,这将正常工作。这就像通过WCF服务发送的复杂类型不喜欢include语句,只是说:"不,不打算这样做"。

参考我的复杂对象,我已经在相当多的黑客,因为它是一个T4生成的对象从数据库(缩写):

[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; }
    }

链接复杂项目的更新:

[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; }
}

我试过删除属性,但还没有与WCF喜欢的"数据成员"类型混淆。我只是不明白为什么这不能工作,因为我发誓我在过去的实体版本4中使用复杂类型的导航属性与其他复杂类型相关。

使用'include'时,复杂对象won'在WCF与实体版本6中的语法

好的,所以我实际上得到了一个朋友的帮助,但我认为这可能会出现在其他人身上,所以我应该回答这个问题,因为它可能会帮助别人。我必须添加一个自定义属性,我为它创建了一个类,以确定循环引用。基本上,当使用WCF时,导航的指针不知何故会丢失,但是当没有连接到服务时,它们是正常的。这不是很好,因为我希望我的服务使用WCF托管方法,而不仅仅是直接使用Entity V6的客户端调用。

    [ServiceContract]
    public interface ICifService
    {
        [OperationContract]
        [CyclicReferencesAware(true)]
        teCIF getCif(int aCifId);
    }

实现类是这样工作的:

    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*/);
        }
    }

一旦我将这个属性应用于我的服务接口中的任何操作,它就可以很好地工作于任何复杂类型。