当我在我的网址上使用过滤器作为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&amp; $ 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)"
}
}
}
}
答案 0 :(得分:0)
查询的$ select部分令人不安。我们还没有试过让$ select和$ expand使用除Linq2Objects和Entityframework之外的任何东西。我们生成的用于获得$ select和$ expand的表达式并且以有效的方式使用Entityframework是非常重要的。
那就是说,你的问题的一个解决方案是采用ODataQueryOptions并在部分中应用查询。在数据库中应用$ filter,$ orderby,$ skip,$ top,然后在第一步之后执行ToList(),在内存中应用$ select和$ expand。
我将继续使用nhibernate来查看我们是否可以改进表达式生成以使此方案正常工作。
答案 1 :(得分:0)
尝试将EnsureStableOrdering = false
添加到QueryableAttribute
:
[Queryable(EnsureStableOrdering = false, AllowedQueryOptions = AllowedQueryOptions.All, PageSize = 20)]
public override IQueryable<T> Get()