2014-01-08 5 views
0

Я использую OData framework 5.0.0 и Web API 5.0.0 и EntityFramework 5.0.0. И есть проблема с расширением свойства навигации, которое является коллекцией. Я всегда получаю следующее исключение:Расширение коллекций с помощью Web Api Контроллер OData

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. 

Развернуть на свойствах, не связанных с коллекцией, работает как шарм.

Это мои 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 выглядит следующим образом:

<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> 

Соответствующие методы в контроллере выглядит следующим образом:

// 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); 
    } 

следующие запросы:

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

/OData/ElementTemplates? $ = Расширение базы

/OData/ElementTemplates? $ = Расширение DefaultTemplateAttribute

Но при доступе к коллекции, я получаю упомянутые выше ошибки:

/OData/ElementTemplates $ развернуть = Элементы

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

Если изменить контроллер таким образом, он предварительно загружает данные:

// 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()); 
    } 

Тогда все запросы работают, но это явно убивает производительность.

Проблема, похоже, похожа на Expanding collections with EntitySetController in MVC Web Api, но они заявляют, что проблема в инфраструктуре NHibernate, которую я, очевидно, не использую, значит, должно быть что-то еще, любая идея?

Я также не испытываю проблемы при использовании той же модели EF с помощью WCF DataServices.

Спасибо!

+0

Оказалось, что Web API добавляет выражение CASE, содержащее идентификатор модели к запросу. Мой код не оценивал это выражение CASE правильно. – mirdus

ответ

0

Оказалось, что Web API добавляет выражение CASE, содержащее идентификатор модели в запрос. Мой код не оценивал это выражение CASE правильно.

+1

Вы могли бы разработать какой-то код? – Jerther

 Смежные вопросы

  • Нет связанных вопросов^_^