0

使用 Visual Studio 2013,我在现有数据库上创建了一个实体模型。每个表都有一个主键的 GUID。我创建了一个带有相关 OData 绑定和控制器的 MVC Web API 项目。

这是我创建 OData 绑定的方法;

ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

builder.EntitySet<HRPosition>("HRPositions").EntityType.HasKey(p=>p.HTPositionGuid);

这是 HRPositions 实体的示例控制器。

   public class HRPositionsController : ODataController
{
    private EFSEntities db = new EFSEntities();

    // GET: odata/HRPositions
    [EnableQuery]
    public IQueryable<HRPosition> GetHRPositions()
    {
        return db.HRPositions;
    }

    // GET: odata/HRPositions(5)
    [EnableQuery]
    public SingleResult<HRPosition> GetHRPosition([FromODataUri] Guid key)
    {
        return SingleResult.Create(db.HRPositions.Where(hRPosition => hRPosition.HTPositionGuid == key));
    }

    // PUT: odata/HRPositions(5)
    public async Task<IHttpActionResult> Put([FromODataUri] Guid key, Delta<HRPosition> patch)
    {
        Validate(patch.GetEntity());

        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        HRPosition hRPosition = await db.HRPositions.FindAsync(key);
        if (hRPosition == null)
        {
            return NotFound();
        }

        patch.Put(hRPosition);

        try
        {
            await db.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!HRPositionExists(key))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return Updated(hRPosition);
    }

    // POST: odata/HRPositions
    public async Task<IHttpActionResult> Post(HRPosition hRPosition)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        db.HRPositions.Add(hRPosition);

        try
        {
            await db.SaveChangesAsync();
        }
        catch (DbUpdateException)
        {
            if (HRPositionExists(hRPosition.HTPositionGuid))
            {
                return Conflict();
            }
            else
            {
                throw;
            }
        }

        return Created(hRPosition);
    }

    // PATCH: odata/HRPositions(5)
    [AcceptVerbs("PATCH", "MERGE")]
    public async Task<IHttpActionResult> Patch([FromODataUri] Guid key, Delta<HRPosition> patch)
    {
        Validate(patch.GetEntity());

        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        HRPosition hRPosition = await db.HRPositions.FindAsync(key);
        if (hRPosition == null)
        {
            return NotFound();
        }

        patch.Patch(hRPosition);

        try
        {
            await db.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!HRPositionExists(key))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return Updated(hRPosition);
    }

    // DELETE: odata/HRPositions(5)
    public async Task<IHttpActionResult> Delete([FromODataUri] Guid key)
    {
        HRPosition hRPosition = await db.HRPositions.FindAsync(key);
        if (hRPosition == null)
        {
            return NotFound();
        }

        db.HRPositions.Remove(hRPosition);
        await db.SaveChangesAsync();

        return StatusCode(HttpStatusCode.NoContent);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }
        base.Dispose(disposing);
    }

    private bool HRPositionExists(Guid key)
    {
        return db.HRPositions.Count(e => e.HTPositionGuid == key) > 0;
    }
}

一旦部署了 OData 服务并使用 Fiddler,我就可以查询服务端点并检索完整的数据列表以及单个实体数据。

然后,我创建了一个 SharePoint 应用程序,在其中我通过引用 OData 服务创建了一个外部内容类型。这将为每个端点创建 ECT 模型定义。

这是 HRPositions 的 ECT;

<?xml version="1.0" encoding="utf-16"?>
<Model xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="EFSData" xmlns="http://schemas.microsoft.com/windows/2007/BusinessDataCatalog">
  <LobSystems>
    <LobSystem Name="EFSODATA" Type="OData">
      <Properties>
        <Property Name="ODataServiceMetadataUrl" Type="System.String">https://efsodataapi.azurewebsites.net/OData/$metadata</Property>
        <Property Name="ODataServiceMetadataAuthenticationMode" Type="System.String">PassThrough</Property>
        <Property Name="ODataServicesVersion" Type="System.String">2.0</Property>
      </Properties>
      <AccessControlList>
        <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
          <Right BdcRight="Edit" />
          <Right BdcRight="Execute" />
          <Right BdcRight="SelectableInClients" />
          <Right BdcRight="SetPermissions" />
        </AccessControlEntry>
      </AccessControlList>
      <LobSystemInstances>
        <LobSystemInstance Name="EFSODATA">
          <Properties>
            <Property Name="ODataServiceUrl" Type="System.String">https://efsodataapi.azurewebsites.net/OData</Property>
            <Property Name="ODataServiceAuthenticationMode" Type="System.String">PassThrough</Property>
            <Property Name="ODataFormat" Type="System.String">application/atom+xml</Property>
            <Property Name="HttpHeaderSetAcceptLanguage" Type="System.Boolean">true</Property>
          </Properties>
        </LobSystemInstance>
      </LobSystemInstances>
      <Entities>
        <Entity Name="HRPositions" DefaultDisplayName="HRPositions" Namespace="EFSData" Version="1.0.0.0" EstimatedInstanceCount="2000">
          <Properties>
            <Property Name="ExcludeFromOfflineClientForList" Type="System.String">False</Property>
          </Properties>
          <AccessControlList>
            <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
              <Right BdcRight="Edit" />
              <Right BdcRight="Execute" />
              <Right BdcRight="SelectableInClients" />
              <Right BdcRight="SetPermissions" />
            </AccessControlEntry>
          </AccessControlList>
          <Identifiers>
            <Identifier Name="HTPositionGuid" TypeName="System.Guid" />
          </Identifiers>
          <Methods>
            <Method Name="CreateHRPosition" DefaultDisplayName="Create HRPosition" IsStatic="false">
              <Properties>
                <Property Name="ODataEntityUrl" Type="System.String">/HRPositions</Property>
              </Properties>
              <AccessControlList>
                <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
                  <Right BdcRight="Edit" />
                  <Right BdcRight="Execute" />
                  <Right BdcRight="SelectableInClients" />
                  <Right BdcRight="SetPermissions" />
                </AccessControlEntry>
              </AccessControlList>
              <Parameters>
                <Parameter Name="@HTPositionGuid" Direction="In">
                  <TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" CreatorField="true" />
                </Parameter>
                <Parameter Name="@PosistionCode" Direction="In">
                  <TypeDescriptor Name="PosistionCode" DefaultDisplayName="PosistionCode" TypeName="System.String" CreatorField="true" />
                </Parameter>
                <Parameter Name="@PositionName" Direction="In">
                  <TypeDescriptor Name="PositionName" DefaultDisplayName="PositionName" TypeName="System.String" CreatorField="true" />
                </Parameter>
                <Parameter Name="@Description" Direction="In">
                  <TypeDescriptor Name="Description" DefaultDisplayName="Description" TypeName="System.String" CreatorField="true" />
                </Parameter>
                <Parameter Name="@CreateHRPosition" Direction="Return">
                  <TypeDescriptor Name="CreateHRPosition" DefaultDisplayName="CreateHRPosition" TypeName="Microsoft.BusinessData.Runtime.DynamicType">
                    <TypeDescriptors>
                      <TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" ReadOnly="true" />
                      <TypeDescriptor Name="PosistionCode" DefaultDisplayName="PosistionCode" TypeName="System.String" />
                      <TypeDescriptor Name="PositionName" DefaultDisplayName="PositionName" TypeName="System.String" />
                      <TypeDescriptor Name="Description" DefaultDisplayName="Description" TypeName="System.String" />
                    </TypeDescriptors>
                  </TypeDescriptor>
                </Parameter>
              </Parameters>
              <MethodInstances>
                <MethodInstance Name="CreateHRPosition" Type="Creator" ReturnParameterName="@CreateHRPosition" ReturnTypeDescriptorPath="CreateHRPosition">
                  <AccessControlList>
                    <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
                      <Right BdcRight="Edit" />
                      <Right BdcRight="Execute" />
                      <Right BdcRight="SelectableInClients" />
                      <Right BdcRight="SetPermissions" />
                    </AccessControlEntry>
                  </AccessControlList>
                </MethodInstance>
              </MethodInstances>
            </Method>
            <Method Name="ReadSpecificHRPosition" DefaultDisplayName="Read Specific HRPosition" IsStatic="false">
              <Properties>
                <Property Name="ODataEntityUrl" Type="System.String">/HRPositions(HTPositionGuid=guid'@HTPositionGuid')</Property>
              </Properties>
              <AccessControlList>
                <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
                  <Right BdcRight="Edit" />
                  <Right BdcRight="Execute" />
                  <Right BdcRight="SelectableInClients" />
                  <Right BdcRight="SetPermissions" />
                </AccessControlEntry>
              </AccessControlList>
              <Parameters>
                <Parameter Name="@HTPositionGuid" Direction="In">
                  <TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" />
                </Parameter>
                <Parameter Name="@HRPosition" Direction="Return">
                  <TypeDescriptor Name="HRPosition" DefaultDisplayName="HRPosition" TypeName="Microsoft.BusinessData.Runtime.DynamicType">
                    <TypeDescriptors>
                      <TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" ReadOnly="true" />
                      <TypeDescriptor Name="PosistionCode" DefaultDisplayName="PosistionCode" TypeName="System.String" />
                      <TypeDescriptor Name="PositionName" DefaultDisplayName="PositionName" TypeName="System.String" />
                      <TypeDescriptor Name="Description" DefaultDisplayName="Description" TypeName="System.String" />
                    </TypeDescriptors>
                  </TypeDescriptor>
                </Parameter>
              </Parameters>
              <MethodInstances>
                <MethodInstance Name="ReadSpecificHRPosition" Type="SpecificFinder" Default="true" ReturnParameterName="@HRPosition" ReturnTypeDescriptorPath="HRPosition">
                  <AccessControlList>
                    <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
                      <Right BdcRight="Edit" />
                      <Right BdcRight="Execute" />
                      <Right BdcRight="SelectableInClients" />
                      <Right BdcRight="SetPermissions" />
                    </AccessControlEntry>
                  </AccessControlList>
                </MethodInstance>
              </MethodInstances>
            </Method>
            <Method Name="ReadAllHRPosition" DefaultDisplayName="Read All HRPosition" IsStatic="false">
              <Properties>
                <Property Name="ODataEntityUrl" Type="System.String">/HRPositions?$top=@LimitHRPositionss</Property>
              </Properties>
              <AccessControlList>
                <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
                  <Right BdcRight="Edit" />
                  <Right BdcRight="Execute" />
                  <Right BdcRight="SelectableInClients" />
                  <Right BdcRight="SetPermissions" />
                </AccessControlEntry>
              </AccessControlList>
              <FilterDescriptors>
                <FilterDescriptor Name="LimitFilter" DefaultDisplayName="LimitFilter" Type="Limit" />
              </FilterDescriptors>
              <Parameters>
                <Parameter Name="@LimitHRPositionss" Direction="In">
                  <TypeDescriptor Name="LimitHRPositionss" DefaultDisplayName="LimitHRPositionss" TypeName="System.Int32" AssociatedFilter="LimitFilter">
                    <Properties>
                      <Property Name="LogicalOperatorWithPrevious" Type="System.String">None</Property>
                      <Property Name="Order" Type="System.String">0</Property>
                    </Properties>
                    <DefaultValues>
                      <DefaultValue MethodInstanceName="ReadAllHRPosition" Type="System.Int32">100</DefaultValue>
                    </DefaultValues>
                  </TypeDescriptor>
                </Parameter>
                <Parameter Name="@HRPositions" Direction="Return">
                  <TypeDescriptor Name="HRPositions" DefaultDisplayName="HRPositions" TypeName="Microsoft.BusinessData.Runtime.IDynamicTypeEnumerator" IsCollection="true">
                    <TypeDescriptors>
                      <TypeDescriptor Name="HRPosition" DefaultDisplayName="HRPosition" TypeName="Microsoft.BusinessData.Runtime.DynamicType">
                        <TypeDescriptors>
                          <TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" ReadOnly="true" />
                          <TypeDescriptor Name="PosistionCode" DefaultDisplayName="PosistionCode" TypeName="System.String" />
                          <TypeDescriptor Name="PositionName" DefaultDisplayName="PositionName" TypeName="System.String" />
                          <TypeDescriptor Name="Description" DefaultDisplayName="Description" TypeName="System.String" />
                        </TypeDescriptors>
                      </TypeDescriptor>
                    </TypeDescriptors>
                  </TypeDescriptor>
                </Parameter>
              </Parameters>
              <MethodInstances>
                <MethodInstance Name="ReadAllHRPosition" Type="Finder" Default="true" ReturnParameterName="@HRPositions" ReturnTypeDescriptorPath="HRPositions">
                  <AccessControlList>
                    <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
                      <Right BdcRight="Edit" />
                      <Right BdcRight="Execute" />
                      <Right BdcRight="SelectableInClients" />
                      <Right BdcRight="SetPermissions" />
                    </AccessControlEntry>
                  </AccessControlList>
                </MethodInstance>
              </MethodInstances>
            </Method>
            <Method Name="UpdateHRPosition" DefaultDisplayName="Update HRPosition" IsStatic="false">
              <Properties>
                <Property Name="ODataEntityUrl" Type="System.String">/HRPositions(HTPositionGuid=guid'@HTPositionGuid')</Property>
              </Properties>
              <AccessControlList>
                <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
                  <Right BdcRight="Edit" />
                  <Right BdcRight="Execute" />
                  <Right BdcRight="SelectableInClients" />
                  <Right BdcRight="SetPermissions" />
                </AccessControlEntry>
              </AccessControlList>
              <Parameters>
                <Parameter Name="@HTPositionGuid" Direction="In">
                  <TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" UpdaterField="true" />
                </Parameter>
                <Parameter Name="@PosistionCode" Direction="In">
                  <TypeDescriptor Name="PosistionCode" DefaultDisplayName="PosistionCode" TypeName="System.String" UpdaterField="true" />
                </Parameter>
                <Parameter Name="@PositionName" Direction="In">
                  <TypeDescriptor Name="PositionName" DefaultDisplayName="PositionName" TypeName="System.String" UpdaterField="true" />
                </Parameter>
                <Parameter Name="@Description" Direction="In">
                  <TypeDescriptor Name="Description" DefaultDisplayName="Description" TypeName="System.String" UpdaterField="true" />
                </Parameter>
              </Parameters>
              <MethodInstances>
                <MethodInstance Name="UpdateHRPosition" Type="Updater">
                  <AccessControlList>
                    <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
                      <Right BdcRight="Edit" />
                      <Right BdcRight="Execute" />
                      <Right BdcRight="SelectableInClients" />
                      <Right BdcRight="SetPermissions" />
                    </AccessControlEntry>
                  </AccessControlList>
                </MethodInstance>
              </MethodInstances>
            </Method>
            <Method Name="DeleteHRPosition" DefaultDisplayName="Delete HRPosition" IsStatic="false">
              <Properties>
                <Property Name="ODataEntityUrl" Type="System.String">/HRPositions(HTPositionGuid=guid'@HTPositionGuid')</Property>
              </Properties>
              <AccessControlList>
                <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
                  <Right BdcRight="Edit" />
                  <Right BdcRight="Execute" />
                  <Right BdcRight="SelectableInClients" />
                  <Right BdcRight="SetPermissions" />
                </AccessControlEntry>
              </AccessControlList>
              <Parameters>
                <Parameter Name="@HTPositionGuid" Direction="In">
                  <TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" />
                </Parameter>
              </Parameters>
              <MethodInstances>
                <MethodInstance Name="DeleteHRPosition" Type="Deleter">
                  <AccessControlList>
                    <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
                      <Right BdcRight="Edit" />
                      <Right BdcRight="Execute" />
                      <Right BdcRight="SelectableInClients" />
                      <Right BdcRight="SetPermissions" />
                    </AccessControlEntry>
                  </AccessControlList>
                </MethodInstance>
              </MethodInstances>
            </Method>
          </Methods>
        </Entity>
      </Entities>
    </LobSystem>
  </LobSystems>
</Model>

我将 ECT 上传到 SharePoint Online BCS 中,一切看起来都很好;

在此处输入图像描述

从那里我创建一个外部列表并引用 HRPositions ECT,它创建和 SP 列表但缺少主键(即 GUID)。

在此处输入图像描述

此视图显示正确的数据; 在此处输入图像描述

我可以在列表中添加一个新项目; 在此处输入图像描述

它显示在阅读所有视图中; 在此处输入图像描述

但是我无法编辑、删除或查看任何列表项,因为每次操作都会出现此错误; 在此处输入图像描述

我附加到 OData Web 服务,可以看到问题发生的原因。事实证明,从 OData 服务反映的 Visual Studio 中的自动生成的外部控制类型 (ECT) 存在问题,因为出于某种原因,它将请求制定为 /HRPositions(HTPositionGuid=guid'@HTPositionGuid');

在此处输入图像描述

它实际上应该只是 /HRPositions(guid'@HTPositionGuid');

谁能告诉我为什么在参数列表中包含 HTPositionGuid=?

我可以为每个实体手动编辑代码生成的 ECT 文件,但这似乎很愚蠢。

4

0 回答 0