扩大使用网页API的OData控制器集合 [英] Expanding collections using Web Api OData controller

查看:223
本文介绍了扩大使用网页API的OData控制器集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的OData框架5.0.0和Web API 5.0.0和5.0.0的EntityFramework。并有扩大的导航属性,它是一个集合的问题。我总是得到以下异常:

I'm using OData framework 5.0.0 and Web API 5.0.0 and EntityFramework 5.0.0. And have problem with expand on navigation property which is a collection. I always get the following exception:

The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.

The given key was not present in the dictionary.

at System.Web.Http.OData.Query.Expressions.SelectExpandWrapper`1.GetEdmType()
at System.Web.Http.OData.Formatter.Serialization.ODataSerializerContext.GetEdmType(Object instance, Type type)
at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteEntry(Object graph, ODataWriter writer, ODataSerializerContext writeContext)
at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteFeed(IEnumerable enumerable, IEdmTypeReference feedType, ODataWriter writer, ODataSerializerContext writeContext)
at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteExpandedNavigationProperty(KeyValuePair`2 navigationPropertyToExpand, EntityInstanceContext entityInstanceContext, ODataWriter writer)
at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteExpandedNavigationProperties(IDictionary`2 navigationPropertiesToExpand, EntityInstanceContext entityInstanceContext, ODataWriter writer)
at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteEntry(Object graph, ODataWriter writer, ODataSerializerContext writeContext)
at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteFeed(IEnumerable enumerable, IEdmTypeReference feedType, ODataWriter writer, ODataSerializerContext writeContext)
at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)
at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.WebHost.HttpControllerHandler.

展开非集合导航属性就像一个魅力。

Expand on non-collection navigation properties works like a charm.

这是我的EF类:

public partial class ElementTemplate
{
    public ElementTemplate()
    {
        this.Elements = new HashSet<Element>();
        this.Derived = new HashSet<ElementTemplate>();
        this.TemplateAttributes = new HashSet<ElementTemplateAttribute>();
    }

    public System.Guid ID { get; set; }
    public string InheritancePath { get; set; }
    public string Name { get; set; }
    public short Level { get; set; }
    public string Description { get; set; }
    public string Type { get; set; }
    public bool AllowElementToExtend { get; set; }
    public Nullable<System.Guid> DefaultElementTemplateAttributeID { get; set; }
    public Nullable<System.Guid> BaseElementTemplateID { get; set; }
    public string SecurityDescriptor { get; set; }
    public Nullable<System.DateTime> CheckOutTime { get; set; }
    public string CheckOutUserName { get; set; }
    public string CheckOutMachineName { get; set; }

    public virtual ICollection<Element> Elements { get; set; }
    public virtual ICollection<ElementTemplate> Derived { get; set; }
    public virtual ElementTemplate Base { get; set; }
    public virtual ElementTemplateAttribute DefaultTemplateAttribute { get; set; }
    public virtual ICollection<ElementTemplateAttribute> TemplateAttributes { get; set; }
}

public partial class Element
{
    public Element()
    {
        this.Attributes = new HashSet<ElementAttribute>();
    }

    public System.Guid ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string Comment { get; set; }
    public int Revision { get; set; }
    public bool HasChildren { get; set; }
    public bool HasMultipleVersions { get; set; }
    public Nullable<System.Guid> ElementTemplateID { get; set; }
    public Nullable<System.Guid> DBReferenceTypeID { get; set; }
    public string SecurityDescriptor { get; set; }
    public System.DateTime Created { get; set; }
    public string CreatedBy { get; set; }
    public System.DateTime Modified { get; set; }
    public string ModifiedBy { get; set; }
    public Nullable<System.DateTime> CheckOutTime { get; set; }
    public string CheckOutUserName { get; set; }
    public string CheckOutMachineName { get; set; }

    public virtual ICollection<ElementAttribute> Attributes { get; set; }
    public virtual ElementTemplate Template { get; set; }
}

有关ElementTemplate元数据如下所示:

The metadata for ElementTemplate looks as follows:

  <EntityType Name="ElementTemplate">
    <Key>
      <PropertyRef Name="ID" />
    </Key>
    <Property Name="ID" Type="Edm.Guid" Nullable="false" />
    <Property Name="InheritancePath" Type="Edm.String" />
    <Property Name="Name" Type="Edm.String" />
    <Property Name="Level" Type="Edm.Int16" Nullable="false" />
    <Property Name="Description" Type="Edm.String" />
    <Property Name="Type" Type="Edm.String" />
    <Property Name="AllowElementToExtend" Type="Edm.Boolean" Nullable="false" />
    <Property Name="DefaultElementTemplateAttributeID" Type="Edm.Guid" />
    <Property Name="BaseElementTemplateID" Type="Edm.Guid" />
    <Property Name="SecurityDescriptor" Type="Edm.String" />
    <Property Name="CheckOutTime" Type="Edm.DateTime" />
    <Property Name="CheckOutUserName" Type="Edm.String" />
    <Property Name="CheckOutMachineName" Type="Edm.String" />
    <NavigationProperty Name="Elements" Relationship="Entity_EntityModel_ElementTemplate_Elements_EntityModel_Element_ElementsPartner" ToRole="Elements" FromRole="ElementsPartner" />
    <NavigationProperty Name="Derived" Relationship="Entity_EntityModel_ElementTemplate_Derived_Entity_EntityModel_ElementTemplate_DerivedPartner" ToRole="Derived" FromRole="DerivedPartner" />
    <NavigationProperty Name="Base" Relationship="Entity_EntityModel_ElementTemplate_Base_Entity_EntityModel_ElementTemplate_BasePartner" ToRole="Base" FromRole="BasePartner" />
    <NavigationProperty Name="DefaultTemplateAttribute" Relationship="Entity_EntityModel_ElementTemplate_DefaultTemplateAttribute_Entity_EntityModel_ElementTemplateAttribute_DefaultTemplateAttributePartner" ToRole="DefaultTemplateAttribute" FromRole="DefaultTemplateAttributePartner" />
    <NavigationProperty Name="TemplateAttributes" Relationship="Entity_EntityModel_ElementTemplate_TemplateAttributesEntity_EntityModel_ElementTemplateAttribute_TemplateAttributesPartner" ToRole="TemplateAttributes" FromRole="TemplateAttributesPartner" />
  </EntityType>

看起来在控制器的有关方法如下:

The relevant methods in the controller looks as follows:

    // GET odata/ElementTemplates
    [Queryable]
    public IQueryable<ElementTemplate> GetElementTemplates()
    {
        return Db.ElementTemplates;
    }

    // GET odata/ElementTemplates(guid'...')
    [Queryable]
    public SingleResult<ElementTemplate> GetElementTemplate([FromODataUri] Guid key)
    {
        return SingleResult.Create(Db.ElementTemplates.Where(elementtemplate => elementtemplate.ID == key));
    }

    // GET odata/ElementTemplates(guid'...')/Elements
    [Queryable]
    public IQueryable<Element> GetElements([FromODataUri] Guid key)
    {
        return Db.ElementTemplates.Where(m => m.ID == key).SelectMany(m => m.Elements);
    }

下面的查询工作:

The following queries work:

/ ODATA / ElementTemplates(GUID'...')/片

/odata/ElementTemplates(guid'...')/Elements

/ ODATA / ElementTemplates?$扩大=基本

/odata/ElementTemplates?$expand=Base

/ ODATA / ElementTemplates?$ =拓展DefaultTemplateAttribute

/odata/ElementTemplates?$expand=DefaultTemplateAttribute

但访问集合时,我得到上述错误:

But when accessing a collection, I get the error mentioned above:

/ ODATA / ElementTemplates?$ =扩展元素

/odata/ElementTemplates?$expand=Elements

/ ODATA / ElementTemplates(GUID'...')?$ =扩展元素

/odata/ElementTemplates(guid'...')?$expand=Elements

如果我的方式改变控制器是pre-加载数据:

If I change the controller in a way it pre-loads the data:

    // GET odata/ElementTemplates
    [Queryable]
    public IQueryable<ElementTemplate> GetElementTemplates()
    {
        return Db.ElementTemplates.ToList().AsQueryable();
    }

    // GET odata/ElementTemplates(guid'...')
    [Queryable]
    public SingleResult<ElementTemplate> GetElementTemplate([FromODataUri] Guid key)
    {
        return SingleResult.Create(Db.ElementTemplates.Where(elementtemplate => elementtemplate.ID == key).ToList().AsQueryable());
    }

然后,所有的查询工作,但它显然杀死的性能。

Then all queries work, but it obviously kills the performance.

这个问题似乎是类似<一个href=\"http://stackoverflow.com/questions/20440449/expanding-collections-with-entitysetcontroller-in-mvc-web-api\">Expanding与EntitySetController集合在MVC网页API ,但他们陈述的问题是NHibernate的框架,我显然没有使用,所以必须有别的东西,任何想法?

The issue seems to be similar to Expanding collections with EntitySetController in MVC Web Api, but they state the problem is in NHibernate framework, which I'm obviously not using, so there must be something else, any idea?

使用通过WCF DataService的同一型号EF时,我也没有遇到这个问题。

I'm also not experiencing the problem when using the same EF model via WCF DataServices.

谢谢!

推荐答案

原来的Web API添加包含模型ID来查询一个CASE前pression。我的code不正确评价这个CASE前pression。

It turned out Web API adds a CASE expression containing the model ID to the query. My code did not evaluate this CASE expression correctly.

这篇关于扩大使用网页API的OData控制器集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆