0

当我在我的 Url 上使用过滤器作为 GET 时/api/modalidades?$orderby=Nome&$select=Nome,Id,会显示错误!

套餐:

FluentNHibernate 1.3.0.733
NHibernate 3.3.3.4000
Microsoft.AspNet.WebApi 5.0.0-rtm-130624
Microsoft.AspNet.WebApi.Client 5.0.0-rtm-130624
Microsoft.AspNet.WebApi.Core 5.0.0-rtm-130624
Microsoft。 AspNet.WebApi.OData 5.0.0-rtm-130624
Microsoft.AspNet.WebApi.Web... 5.0.0-rtm-130624

代码

领域

public class Modalidade : EntityNome
{ }
public abstract class EntityNome : IEntity
{
    public virtual int Id { get; protected internal set; }

    [StringLength(80)]
    [Required]
    public virtual string Nome { get; set; }
}
public interface IEntity : IKeyed<int>
{
}
public interface IKeyed<T> where T : struct
{
    T Id { get; }
}

网络

WebApiConfig.css

public static void Register(HttpConfiguration config)
{
    var modelBuilder = new ODataConventionModelBuilder();

    modelBuilder.EntitySet<Modalidade>("modalidades");
    modelBuilder.Entity<Modalidade>()
        .DerivesFrom<EntityNome>()
        .Property(p => p.Id);

    var model = modelBuilder.GetEdmModel();

    config.Routes.MapODataRoute(routeName: "OData", routePrefix: "api", model: model);

    config.EnableQuerySupport();

    var jsonFormatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
    var enumConverter = new StringEnumConverter();
    jsonFormatter.SerializerSettings.Converters.Add(enumConverter);

    config.Formatters.Remove(config.Formatters.XmlFormatter);
    var jqueryFormatter = config.Formatters.FirstOrDefault(x => x.GetType() == typeof(JQueryMvcFormUrlEncodedFormatter));
    config.Formatters.Remove(config.Formatters.XmlFormatter);
    config.Formatters.Remove(config.Formatters.FormUrlEncodedFormatter);
    config.Formatters.Remove(jqueryFormatter);
    config.Formatters.JsonFormatter.SerializerSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
}

控制器

public class baseApiController<T> : EntitySetController<T, int>
    where T : class, IEntity
{
    public IRepository<T> Repositorio { get; private set; }

    public baseApiController(IRepository<T> repositorio)
    {
        Repositorio = repositorio;
    }

    [Queryable(AllowedQueryOptions = AllowedQueryOptions.All, PageSize = 20)]
    public override IQueryable<T> Get()
    {
        return Repositorio.All();
    }

    [HttpGet, Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
    protected override T GetEntityByKey(int key)
    {
        return Repositorio.Get(key);
    }
}

[Authorize]
public class modalidadesController : baseApiController<Modalidade>
{
    public modalidadesController(IModalidadeRepository repositorio)
        : base(repositorio)
    { }
}

错误

当没有应用过滤器时,一切正常。但是当应用过滤器时,会产生错误!

GET /api/modalidades?$orderby=Nome&$select=Nome,Id HTTP/1.1
主机:localhost:49971
缓存控制:无缓存

{
    "odata.error": {
        "code": "",
        "message": {
            "lang": "en-US",
            "value": "An error has occurred."
        },
        "innererror": {
            "message": "Exception has been thrown by the target of an invocation.",
            "type": "System.Reflection.TargetInvocationException",
            "stacktrace": "   at System.Web.Http.ApiController.<InvokeActionWithExceptionFilters>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()",
            "internalexception": {
                "message": "could not resolve property: class of: CreditoImobiliarioBB.Model.Modalidade [.Take[System.Web.Http.OData.Query.Expressions.SelectExpandWrapper`1[[CreditoImobiliarioBB.Model.Modalidade, CreditoImobiliarioBB.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]](.Select[CreditoImobiliarioBB.Model.Modalidade,System.Web.Http.OData.Query.Expressions.SelectExpandWrapper`1[[CreditoImobiliarioBB.Model.Modalidade, CreditoImobiliarioBB.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]](.ThenBy[CreditoImobiliarioBB.Model.Modalidade,System.Int32](.OrderBy[CreditoImobiliarioBB.Model.Modalidade,System.String](NHibernate.Linq.NhQueryable`1[CreditoImobiliarioBB.Model.Modalidade], Quote(($it, ) => ($it.Nome)), ), Quote(($it, ) => ($it.Id)), ), Quote((, ) => (new SelectExpandWrapper`1()444fb09a-b4c8-43e1-b1f6-d469f9da76eanew NamedPropertyWithNext`1()IdEqual(, NULL) ? NULL : Convert(.Id)new NamedProperty`1()IsType(, CreditoImobiliarioBB.Model.EntityNome) ? Nome : NULLEqual(, NULL) ? NULL : IsType(, CreditoImobiliarioBB.Model.EntityNome) ? TypeAs().Nome : NULL)), ), p8, )]",
                "type": "NHibernate.QueryException",
                "stacktrace": "   at NHibernate.Persister.Entity.AbstractPropertyMapping.ToType(String propertyName)\r\n   at NHibernate.Persister.Entity.AbstractEntityPersister.ToType(String propertyName)\r\n   at NHibernate.Hql.Ast.ANTLR.Tree.FromElementType.GetPropertyType(String propertyName, String propertyPath)\r\n   at NHibernate.Hql.Ast.ANTLR.Tree.FromElement.GetPropertyType(String propertyName, String propertyPath)\r\n   at NHibernate.Hql.Ast.ANTLR.Tree.DotNode.GetDataType()\r\n   at NHibernate.Hql.Ast.ANTLR.Tree.DotNode.PrepareLhs()\r\n   at NHibernate.Hql.Ast.ANTLR.Tree.DotNode.Resolve(Boolean generateJoin, Boolean implicitJoin, String classAlias, IASTNode parent)\r\n   at NHibernate.Hql.Ast.ANTLR.Tree.FromReferenceNode.Resolve(Boolean generateJoin, Boolean implicitJoin, String classAlias)\r\n   at NHibernate.Hql.Ast.ANTLR.Tree.FromReferenceNode.Resolve(Boolean generateJoin, Boolean implicitJoin)\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.Resolve(IASTNode node)\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.expr()\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.exprOrSubquery()\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.comparisonExpr()\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.logicalExpr()\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.caseExpr()\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.arithmeticExpr()\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.selectExpr()\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.selectExprList()\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.selectClause()\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.unionedQuery()\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.query()\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.selectStatement()\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.statement()\r\n   at NHibernate.Hql.Ast.ANTLR.HqlSqlTranslator.Translate()\r\n   at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.Analyze(String collectionRole)\r\n   at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.DoCompile(IDictionary`2 replacements, Boolean shallow, String collectionRole)\r\n   at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.Compile(IDictionary`2 replacements, Boolean shallow)\r\n   at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IASTNode ast, String queryIdentifier, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)\r\n   at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(String queryIdentifier, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)\r\n   at NHibernate.Engine.Query.HQLExpressionQueryPlan.CreateTranslators(String expressionStr, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)\r\n   at NHibernate.Engine.Query.HQLExpressionQueryPlan..ctor(String expressionStr, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)\r\n   at NHibernate.Engine.Query.HQLExpressionQueryPlan..ctor(String expressionStr, IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)\r\n   at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters)\r\n   at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow)\r\n   at NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression)\r\n   at NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery)\r\n   at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)\r\n   at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)\r\n   at Remotion.Linq.QueryableBase`1.GetEnumerator()\r\n   at System.Web.Http.OData.Query.ODataQueryOptions.LimitResults[T](IQueryable`1 queryable, Int32 limit, Boolean& resultsLimited)"
            }
        }
    }
}
4

2 回答 2

0

查询的 $select 部分是令人不安的部分。除了 Linq2Objects 和 Entityframework 之外,我们还没有尝试让 $select 和 $expand 与其他任何东西一起工作。我们为使 $select 和 $expand 以有效的方式与 Entityframework 一起工作而生成的表达式非常重要。

也就是说,解决您的问题的一种方法是采用 ODataQueryOptions 并部分应用查询。在数据库中应用 $filter、$orderby、$skip、$top,然后在第一步之后通过执行 ToList() 在内存中应用 $select 和 $expand。

我将进一步使用 nhibernate,看看我们是否可以改进我们的表达式生成以使这个场景正常工作。

于 2013-07-02T23:04:53.787 回答
0

尝试添加EnsureStableOrdering = false到您的QueryableAttribute

[Queryable(EnsureStableOrdering = false, AllowedQueryOptions = AllowedQueryOptions.All, PageSize = 20)]
public override IQueryable<T> Get()
于 2013-07-03T00:38:46.653 回答