并非所有使用WCF调用的数据都与实体框架包含一起调用

时间:2013-10-17 15:01:25

标签: c# .net wcf entity-framework entity-framework-4

我有一个从实体框架返回数据的WCF服务。它返回的对象是一个ShippingLine,它是OrderLine的子代,它是一个订单的子代。

在我的WCF服务中,我有以下代码:

            var shippingLine = _dbContext.ShippingLines
                            .Include(l => l.OrderLine)
                            .Include(l => l.OrderLine.Order)
                            .Include(l => l.OrderLine.Order.Customer)
                            .Include(l => l.OrderLine.Order.Customer.CustomerAddress)
                            .Include(l => l.OrderLine.Order.Customer.CustomerAddress.Country)
                            .Include(l => l.OrderLine.Order.Customer.CustomerAddress.State)
                            .Include(l => l.OrderLine.OrderLineOptions)
                            .Include(l => l.OrderLine.OrderLineOptions.First().Option)
                            .Include(l => l.OrderLine.OrderLineOptions.First().Option.ExternalPrintingSystemMapping)
                            .Include(l => l.OrderLine.OrderLineStatus)
                            .Include(l => l.TrackingNumbers)
                            .Include(l => l.ShippingMethod)
                            .Include(l => l.ShippingMethod.ShippingRates)
                            .Include(l => l.ShippingBox)
                            .Include(l => l.BulkMailingAsset)
                            .Include(l => l.BulkPostageType)
                            .FirstOrDefault<ShippingLine>(line => line.Id == id);

我们正在围绕EF和自我跟踪实体使用一些自定义扩展方法来帮助我们编写单元测试。我们已经实现了上面调用的自己的Include方法:

            public static IQueryable<TSource> Include<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, object>> exp) where TSource : class
        {
            var objectQuery = source as ObjectQuery<TSource>;

            if (objectQuery != null)
            {
                return objectQuery.Include(ObjectQueryExtensionMethods.GetIncludePath((MemberExpression)exp.Body));
            }

            var fakeObjectSet = source as FakeObjectSet<TSource>;
            if (fakeObjectSet != null)
            {
                fakeObjectSet.Include(exp);
            }

            return source;
        }

        public static IQueryable<TSource> Include<TSource>(this IQueryable<TSource> source, string path) where TSource : class
        {
            var objectQuery = source as ObjectQuery<TSource>;

            if (objectQuery != null)
            {
                return objectQuery.Include(path);
            }

            var fakeObjectSet = source as FakeObjectSet<TSource>;
            if (fakeObjectSet != null)
            {
                fakeObjectSet.Include(path);
            }

            return source;
        }

顶级方法是我目前正在使用的方法。我尝试使用第二个采用字符串页面的“Orderline.Order.Customer”而没有改变行为。顶部的Include方法使用此方法来获取包含路径:

        internal static string GetIncludePath(MemberExpression memberExpression)
    {
        string path = "";
        if (memberExpression.Expression is MethodCallExpression)
            path = GetIncludePath((MemberExpression)((memberExpression.Expression as MethodCallExpression).Arguments[0])) + ".";
        if (memberExpression.Expression is MemberExpression)
            path = GetIncludePath((MemberExpression)memberExpression.Expression) + ".";

        return path + memberExpression.Member.Name;
    }

然后我将此装运行返回给MVC控制器,然后尝试访问OrderLine对象上的订单。由于某种原因,OrderLine对象上的每个属性都为null或设置为其默认值。所以我无法在下面的代码中访问Order对象,因为Order为null:

line.OrderLine.Order.Customer.CustomerAddress;

我正在使用4.0框架和EF 4自我追踪实体。

我确信它包含了OrderLine和Order信息,因为在调试器中我可以在将OrderLine和Order返回给客户端之前正确看到它。

但是,当它到达客户端时,所有OrderLine属性都为null或默认值,而Order不在那里。所有其他包括似乎工作正常。

关系是订单(一)到OrderLine(很多),OrderLine(一)到ShippingLine(很多)。

到目前为止我已经尝试过了...... 1.在客户端上更新我的服务引用。 2.在客户端上删除并重新创建我的服务引用。 3.在客户端上启用详细的WCF跟踪。我没有看到跟踪中的任何问题。

为什么包含这个对象会被丢弃呢? enter image description here

这是我的客户端web.config:

  <system.serviceModel>
<bindings>
  <basicHttpBinding>
    <binding name="BasicHttpBinding_IMyService" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" maxBufferSize="2147483646" maxBufferPoolSize="2147483646" maxReceivedMessageSize="2147483646" messageEncoding="Mtom">
      <readerQuotas maxDepth="256" maxStringContentLength="5242880" maxArrayLength="2147483646" maxBytesPerRead="4096" maxNameTableCharCount="2147483646" />
      <security mode="None">
        <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
    </binding>
  </basicHttpBinding>
</bindings>
<client>
  <endpoint address="http://localhost/MyService/systemservice.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyService" contract="MyService.IMyService" name="BasicHttpBinding_IMyService" />
</client>

这是我的网络服务web.config:

    <system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
    <services>
        <service name="MyApi.MyService">
            <endpoint behaviorConfiguration="MyServiceBehavior" binding="basicHttpBinding" bindingConfiguration="MyServiceBindingConfiguration"
                contract="MyApi.IMyService"/>
            <host>
                <timeouts openTimeout="00:05:00"/>
            </host>
        </service>
    </services>
    <bindings>
        <basicHttpBinding>
            <binding name="MyServiceBindingConfiguration" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
                maxBufferSize="2147483646" maxBufferPoolSize="2147483646" maxReceivedMessageSize="2147483646" messageEncoding="Mtom">
                <readerQuotas maxDepth="256" maxStringContentLength="5242880" maxArrayLength="2147483646" maxBytesPerRead="4096" maxNameTableCharCount="5242880"/>
            </binding>
            <binding name="ServiceSoap" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false"
                bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
                <security mode="Transport">
                    <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
                    <message clientCredentialType="UserName" algorithmSuite="Default"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <!-- productionProxyAddress https://api.authorize.net/soap/v1/Service.asmx -->
        <endpoint address="https://apitest.authorize.net/soap/v1/Service.asmx" binding="basicHttpBinding" bindingConfiguration="ServiceSoap"
            contract="AuthorizeNet.ServiceSoap" name="ServiceSoap"/>
    </client>
    <behaviors>
        <endpointBehaviors>
            <behavior name="MyServiceBehavior">
            </behavior>
        </endpointBehaviors>
        <serviceBehaviors>
            <behavior>
                <serviceMetadata httpGetEnabled="True"/>
                <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>

2 个答案:

答案 0 :(得分:0)

我认为EF包括用于包含集合的lambda语法是

.Include(l => l.OrderLine.OrderLineOptions.Select(ol => ol.Option)) 

而不是

.Include(l => l.OrderLine.OrderLineOptions.First().Option)

答案 1 :(得分:0)

我通过引用我们称为ServiceInterface的项目(而不是服务)来解决它。此项目的唯一目的是为我们的Web服务提供服务引用。因为我们引用服务是几个地方,这使得添加新方法更容易。您只需在一个地方更新服务参考。

我唯一能想到的是由于某种原因,当我添加服务引用时,我的MVC站点项目上创建的代理类没有正确创建。无论我更新它多少次或重新创建服务引用,它都行不通。使用具有服务参考的项目我知道有效。