2013-09-23 20 views
1

我有一個與odata的asp.net wep api項目,但我有一些odata過濾機制的問題。 ?在Asp.net上的高級過濾器Wep Api OData

當我執行該查詢

/API /值$頂部= 1 & $過濾器=評論/任何(C:C /身份證EQ 64)

它給了我以下錯誤

{ 
"Message": "An error has occurred.", 
"ExceptionMessage": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.", 
"ExceptionType": "System.InvalidOperationException", 
"StackTrace": null, 
"InnerException": { 
    "Message": "An error has occurred.", 
    "ExceptionMessage": "Cannot compare elements of type 'System.Linq.IQueryable`1'. Only primitive types, enumeration types and entity types are supported.", 
    "ExceptionType": "System.NotSupportedException", 
    "StackTrace": " at System.Data.Objects.ELinq.ExpressionConverter.VerifyTypeSupportedForComparison(Type clrType, TypeUsage edmType, Stack`1 memberPath)\r\n at System.Data.Objects.ELinq.ExpressionConverter.CreateIsNullExpression(DbExpression operand, Type operandClrType)\r\n at System.Data.Objects.ELinq.ExpressionConverter.EqualsTranslator.CreateIsNullExpression(ExpressionConverter parent, Expression input)\r\n at System.Data.Objects.ELinq.ExpressionConverter.EqualsTranslator.TypedTranslate(ExpressionConverter parent, BinaryExpression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.ConditionalTranslator.TypedTranslate(ExpressionConverter parent, ConditionalExpression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.EqualsTranslator.TypedTranslate(ExpressionConverter parent, BinaryExpression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding)\r\n at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)\r\n at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)\r\n at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)\r\n at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)\r\n at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)\r\n at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)\r\n at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)\r\n at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)\r\n at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)\r\n at System.Data.Objects.ELinq.ExpressionConverter.Convert()\r\n at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)\r\n at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)\r\n at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()\r\n at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)\r\n at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)\r\n at Newtonsoft.Json.Serialization.JsonArrayContract.CreateWrapper(Object list)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value)\r\n at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value)\r\n at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value)\r\n at System.Net.Http.Formatting.JsonMediaTypeFormatter.<>c__DisplayClassd.<WriteToStreamAsync>b__c()\r\n at System.Threading.Tasks.TaskHelpers.RunSynchronously(Action action, CancellationToken token)" 
} 

}

但是,當我執行以下CONTRO米勒代替OData的過濾器,一切都很好,

[Queryable] 
    public IQueryable<FortuneDTO> Get() 
    { 
     return service.FilterBy().Where(_ => _.Comments.Any(c => c.Id == 64)); 
    } 

我使用存儲庫+服務層圖案在我的項目,我的項目的結構就是這樣

API控制器< - >服務< - >存儲庫< - > EF

的OData API控制器

[Queryable] 
    public IQueryable<FortuneDTO> Get() 
    { 
     return service.FiterBy(); 
    } 

服務

public IQueryable<FortuneDTO> FiterBy() 
    { 
     return repository.List().Select(_ => new FortuneDTO 
     { 
      CreatedByFullName = _.aspnet_Users.FullName, 
      Id = _.FortuneId, 
      Comments = _.tblComment.Select(c => new CommentDTO 
      { 
       Id=c.CommentId, 
       Comment = c.Comment, 
       Fortuneteller = new FortunetellerDTO { 
        FullName=c.aspnet_Users.FullName, 
        Id=c.aspnet_Users.UserId 
       } 
      }).AsQueryable() 
     }); 
    } 

public virtual IQueryable<TEntity> List() 
    { 
     return context.CreateObjectSet<TEntity>(); 
    } 

DTO的

public class FortuneDTO 
{ 
    public int Id { get; set; } 
    public string CreatedByFullName { get; set; } 
    public IQueryable<CommentDTO> Comments { get; set; } 
} 
public class CommentDTO 
{ 
    public int Id { get; set; } 
    public string Comment { get; set; } 
    public FortunetellerDTO Fortuneteller { get; set; } 
} 
public class FortunetellerDTO 
{ 
    public Guid Id { get; set; } 
    public string FullName { get; set; } 
} 

我不能鰭d沒有辦法避免這個錯誤

編輯:

生成並執行表達

Convert(value(System.Data.Objects.ObjectSet`1[Axiom.Entities.tblFortune])).MergeAs(AppendOnly).Where(_ => True).Select(_ => new FortuneDTO() {CreatedByFullName = _.aspnet_Users.FullName, Id = _.FortuneId, Comments = _.tblComment.Select(c => new CommentDTO() {Id = c.CommentId, Comment = c.Comment, Fortuneteller = new FortunetellerDTO() {FullName = c.aspnet_Users.FullName, Id = c.aspnet_Users.UserId}}).AsQueryable()}).Where($it => (IIF(($it.Comments == null), null, Convert($it.Comments.Any(c => ($it.Id == value(System.Web.Http.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.Int32]).TypedProperty)))) == True)) 

實體框架4 的ASP.NET Web API 4.0.30506.0

+0

您是否在'FortuneDTO'中嘗試過'ICollection '而不是'IQueryable '? –

+0

當我嘗試ICollection 時,它在服務層的FilterBy方法中給出了轉換錯誤。我不知道我應該從這裏回來'Comments = _.tblComment.Select(c => new CommentDTO { ID = c。CommentId, 註釋= c.Comment, 命理=新FortunetellerDTO { 全名= c.aspnet_Users.FullName, 編號= c.aspnet_Users.UserId } })。AsQueryable已()' – emreturan

+0

確定我看到。嘗試返回'IEnumerable '而不是'.AsQueryable()'使用'.AsEnumerable()'。然後雙方都應該很高興...... –

回答

2

我覺得網絡API未能檢測到您正在使用entityframework(可能是因爲您正在使用entityframework 4.0)並且正在開啓NullPropagation。您可以通過這樣做明確地關閉它,

[Queryable(HandleNullPropagation=false)] 

並查看它是否有效。

+0

對不起,它仍然拋出相同的錯誤'無法比較類型'System.Linq.IQueryable'1'的元素。只支持原始類型(如Int32,String和Guid)和實體類型.' – emreturan

+0

您能否啓用「break on exception」並查看實體框架IQueryable的表達式是什麼?這將有助於弄清楚什麼是錯的。謝謝。 –

+0

我剛剛編輯帖子並添加了表達式 – emreturan