Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将表值函数作为Web Api 2 OData v4服务中实体集的属性公开?_C#_Entity Framework_Asp.net Web Api_Odata_Asp.net Web Api Odata - Fatal编程技术网

C# 如何将表值函数作为Web Api 2 OData v4服务中实体集的属性公开?

C# 如何将表值函数作为Web Api 2 OData v4服务中实体集的属性公开?,c#,entity-framework,asp.net-web-api,odata,asp.net-web-api-odata,C#,Entity Framework,Asp.net Web Api,Odata,Asp.net Web Api Odata,请告诉我如何将表值函数作为Web Api 2 OData v4服务中实体集的属性公开 我的简化模式有三个表、结构、位置和位置链接。结构包含一个带有节点(locaton)和边(LocationLinks)的图。我使用EntityFramework6数据库访问第一个模型 Simplified Schema Structure: ID Locations: ID ParentID -> Structure LocationLinks

请告诉我如何将表值函数作为Web Api 2 OData v4服务中实体集的属性公开

我的简化模式有三个表、结构、位置和位置链接。结构包含一个带有节点(locaton)和边(LocationLinks)的图。我使用EntityFramework6数据库访问第一个模型

Simplified Schema

  Structure:
      ID

  Locations:
      ID
      ParentID -> Structure

  LocationLinks
      A -> Location
      B -> Location
目标是访问LocationLinks的structures集合,与访问结构位置的方式相同。i、 e.请求结构#180的图形:

http://.../OData/Structures(180)/LocationLinks
http://.../OData/Structures(180)/Locations
Locations查询自动工作,但我不知道如何添加正确的路由以启用LocationLinks查询。考虑到这会使我的任务更简单,我在SQL server中添加了一个表值函数。该函数存在于my EF模型中,并返回LocationLink实体的集合:

StructureLocationLinks(@StructureID) -> LocationLinks
不幸的是,无论我尝试什么,我似乎都无法使结构(180)\LocationLinks URL正常工作。这是我的最新尝试:

StructuresController.cs代码段:

        // GET: odata/Structures(5)/Locations
        [EnableQuery]
        public IQueryable<Location> GetLocations([FromODataUri] long key)
        {
            return db.Structures.Where(m => m.ID == key).SelectMany(m => m.Locations);
        }

        // GET: odata/Structures(5)/LocationLinks
        [EnableQuery]        
        //[System.Web.OData.Routing.ODataRoute("Structures({key})")]
        public IQueryable<LocationLink> GetLocationLinks([FromODataUri] long key)
        {
            return db.StructureLocationLinks(key);
        }
public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
            json.UseDataContractJsonSerializer = true;
            //json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All;

            //var cors = new System.Web.Http.Cors.EnableCorsAttribute("*", "*", "*");
            //config.EnableCors(cors);

            // Web API routes 
            config.MapHttpAttributeRoutes();

            ODataConventionModelBuilder builder = GetModel();

            config.MapODataServiceRoute(routeName: "odata",
                routePrefix: null,
                model: builder.GetEdmModel());

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }

    public static ODataConventionModelBuilder GetModel()
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

            builder.Namespace = typeof(Structure).Namespace;

            AddLocationLinks(builder);
            AddStructures(builder);
            builder.EntitySet<Location>("Locations");

            return builder;
        }

        public static void AddStructures(ODataModelBuilder builder)
        {
            var structSetconfig = builder.EntitySet<Structure>("Structures");
            var structConfig = structSetconfig.EntityType;

            var functionConfig = structConfig.Collection.Function("StructureLocationLinks");
            functionConfig.Parameter<long>("StructureID");
            functionConfig.Returns<LocationLink>();
        }


        public static void AddLocationLinks(ODataModelBuilder builder)
        {
            var type = builder.EntityType<LocationLink>();
            type.HasKey(sl => sl.A);
            type.HasKey(sl => sl.B);
            builder.EntitySet<LocationLink>("LocationLinks");
        }
现在的问题是,我在查询中访问导航属性的能力有限。例如,此链接起作用:

http://.../OData/Structures(180)/Children?$expand=Locations
但事实并非如此

http://.../OData/Structures(180)/Children?$expand=LocationLinks
返回的错误是

{“错误”:{ “代码”:”“消息”:“发生错误”。、“内部错误”: { “消息”:“未为“ConnectomeDataModel.Structure”类型定义实例属性“LocationLinks”, “type”:“System.ArgumentException”,“stacktrace”:“at System.Linq.Expressions.Expression.Property(Expression, 字符串propertyName)\r\n位于 System.Web.OData.Query.Expressions.SelectExpandBinder.CreatePropertyValueExpressionWithFilter(IEdmEntityType elementType、IEdmProperty属性、表达式源、FilterClause filterClause)\r\n位于 System.Web.OData.Query.Expressions.SelectExpandBinder.BuildPropertyContainer(IEdmEntityType elementType,表达式源,Dictionary
2属性展开,
ISet
1属性包括,ISet
1自动选择属性,布尔值
IsSelectingPentypeSegments)\r\n位于
System.Web.OData.Query.Expressions.SelectExpandBinder.ProjectElement(表达式
source,SelectExpandClause SelectExpandClause,IEdmEntityType
entityType)\r\n位于
System.Web.OData.Query.Expressions.SelectExpandBinder.Bind(IQueryable
可查询)\r\n位于
System.Web.OData.Query.ODataQueryOptions.ApplySelectExpand[T](T
实体,ODataQuerySettings查询设置)\r\n位于
System.Web.OData.Query.ODataQueryOptions.ApplyTo(IQueryable查询,
ODataQuerySettings查询设置)\r\n位于
System.Web.OData.EnableQueryAttribute.ExecuteQuery(对象响应,
HttpRequestMessage请求,HttpActionDescriptor actionDescriptor)\r\n
在
System.Web.OData.EnableQueryAttribute.OnActionExecuted(HttpActionExecutedContext
actionExecutedContext)\r\n位于
System.Web.Http.Filters.ActionFilterAttribute.OnActionExecutedAsync(HttpActionExecutedContext
ActionExecuteContext,CancellationToken CancellationToken)\r\n---结束
从引发异常的上一个位置开始的堆栈跟踪的
---\r\n在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务
任务)\r\n位于
System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotification(任务
任务)\r\n位于
System.Web.Http.Filters.ActionFilterAttribute.d\u 5.MoveNext()\r\n---
来自引发异常的上一个位置的堆栈结束跟踪
---\r\n在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务
任务)\r\n位于
System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotification(任务
任务)\r\n位于
System.Web.Http.Filters.ActionFilterAttribute.d\u 0.MoveNext()\r\n---
来自引发异常的上一个位置的堆栈结束跟踪
---\r\n在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务
任务)\r\n位于
System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotification(任务
任务)\r\n位于
System.Runtime.CompilerServices.TaskAwaiter
1.GetResult()\r\n位于 System.Web.Http.Controllers.ActionFilterResult.d\u 2.MoveNext()\r\n--- 来自引发异常的上一个位置的堆栈结束跟踪 ---\r\n在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)\r\n位于 System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)\r\n位于 System.Runtime.CompilerServices.TaskWaiter`1.GetResult()\r\n位于 System.Web.Http.Dispatcher.HttpControllerDispatcher.d_u1.MoveNext() }}}

Xycor

正如您提到的,
位置链接
应该与
结构的
位置
相同。所以,我认为你们为控制器和行动所做的是正确的。我有一个基于您描述的测试,似乎Web API OData可以按照约定路由
GetLocationLinks

让我展示我的元数据文档,请忽略名称空间,将其与您的进行比较,并让我知道任何差异。谢谢

<Schema Namespace="ODataConsoleSample" xmlns="http://docs.oasis-open.org/odata/ns/edm">
  <EntityType Name="LocationLink">
    <Key>
      <PropertyRef Name="A" />
      <PropertyRef Name="B" />
    </Key>
    <Property Name="A" Type="Edm.Int64" Nullable="false" />
    <Property Name="B" Type="Edm.Int64" Nullable="false" />
  </EntityType>
  <EntityType Name="Structure">
    <Key>
      <PropertyRef Name="Id" />
    </Key>
    <Property Name="Id" Type="Edm.Int64" Nullable="false" />
    <NavigationProperty Name="Locations" Type="Collection(ODataConsoleSample.Location)" />
    <NavigationProperty Name="LocationLinks" Type="Collection(ODataConsoleSample.LocationLink)" />
  </EntityType>
  <EntityType Name="Location">
    <Key>
      <PropertyRef Name="Id" />
    </Key>
    <Property Name="Id" Type="Edm.Int64" Nullable="false" />
    <Property Name="ParentId" Type="Edm.Int64" Nullable="false" />
  </EntityType>
  <Function Name="StructureLocationLinks" IsBound="true">
    <Parameter Name="bindingParameter" Type="Collection(ODataConsoleSample.Structure)" />
    <Parameter Name="StructureID" Type="Edm.Int64" Nullable="false" />
    <ReturnType Type="ODataConsoleSample.LocationLink" />
  </Function>
  <EntityContainer Name="Container">
    <EntitySet Name="LocationLinks" EntityType="ODataConsoleSample.LocationLink" />
    <EntitySet Name="Structures" EntityType="ODataConsoleSample.Structure">
      <NavigationPropertyBinding Path="Locations" Target="Locations" />
      <NavigationPropertyBinding Path="LocationLinks" Target="LocationLinks" />
    </EntitySet>
    <EntitySet Name="Locations" EntityType="ODataConsoleSample.Location" />
  </EntityContainer>
</Schema>


这看起来很合理。但是,我认为在配置OData服务时必须添加导航属性。我拥有的EDMX是从数据库生成的。这是EDMX的函数导入。当我将IsBound=“True”属性设置为函数定义时,我得到一个属性not allowed错误。请忽略上面的注释。我无意中发了帖子,当我把它编辑成合适的形状时,它被锁上了。这是正确的回答:看起来很合理。但是,我认为在配置OData服务时,必须将NavigationProperty添加到ODataConventionBuilder。我拥有的EDMX是从数据库生成的。我的功能是d
http://.../OData/Structures(180)/Children?$expand=LocationLinks
<Schema Namespace="ODataConsoleSample" xmlns="http://docs.oasis-open.org/odata/ns/edm">
  <EntityType Name="LocationLink">
    <Key>
      <PropertyRef Name="A" />
      <PropertyRef Name="B" />
    </Key>
    <Property Name="A" Type="Edm.Int64" Nullable="false" />
    <Property Name="B" Type="Edm.Int64" Nullable="false" />
  </EntityType>
  <EntityType Name="Structure">
    <Key>
      <PropertyRef Name="Id" />
    </Key>
    <Property Name="Id" Type="Edm.Int64" Nullable="false" />
    <NavigationProperty Name="Locations" Type="Collection(ODataConsoleSample.Location)" />
    <NavigationProperty Name="LocationLinks" Type="Collection(ODataConsoleSample.LocationLink)" />
  </EntityType>
  <EntityType Name="Location">
    <Key>
      <PropertyRef Name="Id" />
    </Key>
    <Property Name="Id" Type="Edm.Int64" Nullable="false" />
    <Property Name="ParentId" Type="Edm.Int64" Nullable="false" />
  </EntityType>
  <Function Name="StructureLocationLinks" IsBound="true">
    <Parameter Name="bindingParameter" Type="Collection(ODataConsoleSample.Structure)" />
    <Parameter Name="StructureID" Type="Edm.Int64" Nullable="false" />
    <ReturnType Type="ODataConsoleSample.LocationLink" />
  </Function>
  <EntityContainer Name="Container">
    <EntitySet Name="LocationLinks" EntityType="ODataConsoleSample.LocationLink" />
    <EntitySet Name="Structures" EntityType="ODataConsoleSample.Structure">
      <NavigationPropertyBinding Path="Locations" Target="Locations" />
      <NavigationPropertyBinding Path="LocationLinks" Target="LocationLinks" />
    </EntitySet>
    <EntitySet Name="Locations" EntityType="ODataConsoleSample.Location" />
  </EntityContainer>
</Schema>