c# OData创建(POST)带有嵌套项的请求

本文关键字:嵌套 请求 OData 创建 POST | 更新日期: 2023-09-27 18:12:49

希望有人能帮我解决我遇到的问题。我们正在使用一个新产品,它与我们的ERP系统交互,并通过使用OData的REST服务公开业务对象。他们有一些样品和我用过的所有东西,但我被一个我们试图使用该产品的关键过程卡住了,那就是在一个请求中创建一个包含许多项目的销售文档。

我已经让后端工作在服务器端接受请求,因为我可以在Firefox中使用REST客户端手动创建POST请求,ERP系统接受请求并创建文档,没有问题。

问题是,我试图通过简单的c#控制台应用程序以编程方式创建请求,但我无法正确创建请求。

OData服务的元数据如下:

<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:gp="http://www.sap.com/Protocols/SAPData/GenericPlayer" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:sap="http://www.sap.com/Protocols/SAPData" Version="1.0">
  <edmx:DataServices m:DataServiceVersion="2.0">
    <Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" Namespace="SALES_ORDER">
      <EntityType Name="SalesOrderHeader" sap:content-version="1">
        <Key>
          <PropertyRef Name="OrderId"/>
        </Key>
        <Property Name="OrderId" Type="Edm.String" Nullable="false" MaxLength="10" sap:label="Sales Document" sap:filterable="false"/>
        <Property Name="DocumentType" Type="Edm.String" MaxLength="4" sap:label="Sales Doc. Type" sap:filterable="false"/>
        <Property Name="DocumentDate" Type="Edm.DateTime" Precision="10" sap:label="Document Date" sap:filterable="false"/>
        <Property Name="CustomerId" Type="Edm.String" MaxLength="10" sap:label="Sold-to party" sap:filterable="true"/>
        <Property Name="SalesOrg" Type="Edm.String" MaxLength="4" sap:label="Sales Org." sap:filterable="false"/>
        <Property Name="DistChannel" Type="Edm.String" MaxLength="2" sap:label="Distr. Channel" sap:filterable="false"/>
        <Property Name="Division" Type="Edm.String" MaxLength="2" sap:label="Division" sap:filterable="false"/>
        <Property Name="OrderValue" Type="Edm.Decimal" Precision="21" Scale="2" sap:label="Net value" sap:filterable="false"/>
        <Property Name="Currency" Type="Edm.String" MaxLength="5" sap:label="Doc. Currency" sap:filterable="false" sap:semantics="currency-code"/>
        <NavigationProperty Name="SalesOrderItems" Relationship="SALES_ORDER.SalesOrderHeader_SalesOrderItems" FromRole="FromRole_SalesOrderHeader_SalesOrderItem" ToRole="ToRole_SalesOrderItem_SalesOrderHeader"/>
      </EntityType>
      <EntityType Name="SalesOrderItem" sap:content-version="1">
        <Key>
          <PropertyRef Name="OrderId"/>
          <PropertyRef Name="Item"/>
        </Key>
        <Property Name="OrderId" Type="Edm.String" Nullable="false" MaxLength="10" sap:label="Sales Document" sap:filterable="false"/>
        <Property Name="Item" Type="Edm.String" Nullable="false" MaxLength="6" sap:label="Item" sap:filterable="false"/>
        <Property Name="Material" Type="Edm.String" MaxLength="18" sap:label="Material" sap:filterable="false"/>
        <Property Name="Description" Type="Edm.String" MaxLength="40" sap:label="Description" sap:filterable="false"/>
        <Property Name="Plant" Type="Edm.String" MaxLength="4" sap:label="Plant" sap:filterable="false"/>
        <Property Name="Quantity" Type="Edm.Decimal" Precision="19" Scale="3" sap:label="Order quantity" sap:filterable="false"/>
        <Property Name="UOM" Type="Edm.String" MaxLength="3" sap:label="Sales unit" sap:filterable="false" sap:semantics="unit-of-measure"/>
        <Property Name="Value" Type="Edm.Decimal" Precision="21" Scale="2" sap:label="Net value" sap:filterable="false"/>
        <NavigationProperty Name="SalesOrderHeader" Relationship="SALES_ORDER.SalesOrderItem_SalesOrderHeader" FromRole="FromRole_SalesOrderItem_SalesOrderHeader" ToRole="ToRole_SalesOrderHeader_SalesOrderItem"/>
      </EntityType>
      <Association Name="SalesOrderHeader_SalesOrderItems" sap:content-version="1">
        <End Type="SALES_ORDER.SalesOrderHeader" Multiplicity="1" Role="FromRole_SalesOrderHeader_SalesOrderItem"/>
        <End Type="SALES_ORDER.SalesOrderItem" Multiplicity="*" Role="ToRole_SalesOrderItem_SalesOrderHeader"/>
      </Association>
      <Association Name="SalesOrderItem_SalesOrderHeader" sap:content-version="1">
        <End Type="SALES_ORDER.SalesOrderItem" Multiplicity="1" Role="FromRole_SalesOrderItem_SalesOrderHeader"/>
        <End Type="SALES_ORDER.SalesOrderHeader" Multiplicity="1" Role="ToRole_SalesOrderHeader_SalesOrderItem"/>
      </Association>
      <EntityContainer Name="SALES_ORDER" m:IsDefaultEntityContainer="true">
        <EntitySet Name="SalesOrderHeaders" EntityType="SALES_ORDER.SalesOrderHeader" sap:content-version="1"/>
        <EntitySet Name="SalesOrderItems" EntityType="SALES_ORDER.SalesOrderItem" sap:content-version="1"/>
        <AssociationSet Name="AssocSet_SalesOrderHeader_SalesOrderItems" Association="SALES_ORDER.SalesOrderHeader_SalesOrderItems" sap:content-version="1">
          <End EntitySet="SalesOrderHeaders" Role="FromRole_SalesOrderHeader_SalesOrderItem"/>
          <End EntitySet="SalesOrderItems" Role="ToRole_SalesOrderItem_SalesOrderHeader"/>
        </AssociationSet>
        <AssociationSet Name="AssocSet_SalesOrderItem_SalesOrderHeader" Association="SALES_ORDER.SalesOrderItem_SalesOrderHeader" sap:content-version="1">
          <End EntitySet="SalesOrderItems" Role="FromRole_SalesOrderItem_SalesOrderHeader"/>
          <End EntitySet="SalesOrderHeaders" Role="ToRole_SalesOrderHeader_SalesOrderItem"/>
        </AssociationSet>
      </EntityContainer>
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>

现在,如果我手动创建一个请求(按照软件供应商的指示),服务器接受请求并在ERP系统中创建文档。这个请求是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<atom:entry
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
  <atom:content type="application/xml">
    <m:properties>
      <d:DocumentType>ZCSH</d:DocumentType>
      <d:CustomerId>0001008657</d:CustomerId>
      <d:SalesOrg>1100</d:SalesOrg>
      <d:DistChannel>10</d:DistChannel>
      <d:Division>40</d:Division>
    </m:properties>
  </atom:content>
  <atom:link
  href="SalesOrderHeaders(0000004970)/SalesOrderItems"
  rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/SalesOrderItems"
  type="application/atom+xml;type=feed"
  title="SALES_ORDER.SalesOrderHeader_SalesOrderItems">
    <m:inline>
      <atom:feed>
        <atom:entry>
          <atom:content type="application/xml">
            <m:properties>
              <d:Item>000010</d:Item>
              <d:Material>70000559</d:Material>
              <d:Plant>570B</d:Plant>
              <d:Quantity m:Type="Edm.Decimal">1.000</d:Quantity>
            </m:properties>
          </atom:content>
        </atom:entry>
        <atom:entry>
          <atom:content type="application/xml">
            <m:properties>
              <d:Item>000020</d:Item>
              <d:Material>70000559</d:Material>
              <d:Plant>570B</d:Plant>
              <d:Quantity m:Type="Edm.Decimal">5</d:Quantity>
            </m:properties>
          </atom:content>
        </atom:entry>
      </atom:feed>
    </m:inline>
  </atom:link>
</atom:entry>
然而,在c#中使用以下代码,我无法使Items成为请求的一部分。他们就是不出现。这里是c#:
ServiceReference4.SALES_ORDER ser = new ServiceReference4.SALES_ORDER(uri);
        NetworkCredential c = nc;
        ser.WritingEntity += new EventHandler<System.Data.Services.Client.ReadingWritingEntityEventArgs>(ser_WritingEntity);
        ser.SendingRequest += new EventHandler<System.Data.Services.Client.SendingRequestEventArgs>(ser_SendingRequest);
        ser.Credentials = c;
        ServiceReference4.SalesOrderHeader soHeader = new ServiceReference4.SalesOrderHeader();
        ServiceReference4.SalesOrderItem soItem = new ServiceReference4.SalesOrderItem();
        soHeader = ServiceReference4.SalesOrderHeader.CreateSalesOrderHeader("");
        soHeader.DocumentType = "ZCSH";
        soHeader.DistChannel = "10";
        soHeader.Division = "40";
        soHeader.SalesOrg = "1100";            
        soItem = ServiceReference4.SalesOrderItem.CreateSalesOrderItem("", "10".PadLeft(6, '0'));
        soItem.Material = "70000559".PadLeft(18, '0');
        soItem.Plant = "570B";
        soItem.Quantity = 1;
        soItem.SalesOrderHeader = soHeader;
        soHeader.SalesOrderItems.Add(soItem);
        ser.AddToSalesOrderHeaders(soHeader);
        try
        {                
            System.Data.Services.Client.DataServiceResponse resp = ser.SaveChanges();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message + Environment.NewLine + ex.InnerException);
        }

但是这是生成的请求:

<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
  <category scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" term="SALES_ORDER.SalesOrderHeader" />
  <title />
  <author>
    <name />
  </author>
  <updated>2011-10-31T20:27:42.5387007Z</updated>
  <id>http://.../sap/opu/sdata/sap/SALES_ORDER/SalesOrderHeaders('')</id>
  <content type="application/xml">
    <m:properties>
      <d:Currency m:null="true" />
      <d:CustomerId m:null="true" />
      <d:DistChannel>10</d:DistChannel>
      <d:Division>40</d:Division>
      <d:DocumentDate m:type="Edm.DateTime" m:null="true" />
      <d:DocumentType>ZCSH</d:DocumentType>
      <d:OrderId m:null="false" />
      <d:OrderValue m:type="Edm.Decimal" m:null="true" />
      <d:SalesOrg>1100</d:SalesOrg>
    </m:properties>
  </content>
</entry>
我希望这是有意义的…如有任何帮助,不胜感激。

谢谢

c# OData创建(POST)带有嵌套项的请求

您需要显式地告诉数据服务上下文(ser)这些对象之间存在链接。看看AddLink和SetLink方法。这些页面上的例子非常接近你要做的。

总之,我认为你需要加上:

ser.AddLink(soHeader, "SalesOrderItems", soItem);
ser.SetLink(soItem, "SalesOrderHeader", soHeader);

嗯,根据MS论坛上的家伙,这种类型的深度插入请求目前不支持WCF DS客户端。

大型游手好闲的人。