OData$expand、DTO和实体框架我有一个基本的WebApi服务设置,首先使用EFDataModel设置数据库。我正在运行WebApi、EF6和WebApiOData包的夜间构建。(WebApi:5.1.0-alpha1,EF:6.1.0-alpha1,WebApiOData:5.1.0-alpha1)数据库有两个表:产品和供应商。一个产品可以有一个供应商。一个供应商可以有多个产品。我还创建了两个DTO类:publicclassSupplier{[Key]publicintId{get;放;}公共字符串名称{得到;放;}publicvirtualIQueryableProducts{get;放;}}publicclassProduct{[Key]publicintId{get;放;}公共字符串名称{得到;放;我已经设置了我的WebApiConfig如下:publicstaticvoidRegister(HttpConfigurationconfig){oDataModelBuilder.EntitySet("产品");oDataModelBuilder.EntitySet("供应商");config.Routes.MapODataRoute(routeName:"oData",routePrefix:"odata",model:oDataModelBuilder.GetEdmModel());}我将其设置如下创建了两个控制器:varresults=context.EF_Products.Select(x=>newProduct(){Id=x.ProductId,Name=x.ProductName});将结果作为IQueryable返回;}}公共类SupplierController:ODataController{[HttpGet][Queryable]publicIQueryableGet(){varcontext=newExampleContext();varresults=context.EF_Suppliers.Select(x=>newSupplier(){Id=x.SupplierId,Name=x.SupplierName});将结果作为IQueryable返回;这是返回的元数据如您所见,导航属性设置正确:所以正常的odata查询数组工作正常:/odata/product?$filter=Name+eq+'Product1'and/odata/supplier?$select=Id例如一切正常。问题是当我尝试使用$expand时。如果我做/odata/supplier怎么办?$expand=Products当然我得到错误:“LINQtoEntities不支持指定的类型成员‘Products’。仅支持初始化程序、实体成员和实体导航属性。”更新:我不断收到同样的问题,所以我添加了更多信息。是的,导航属性设置正确,如上面发布的元数据信息所示。这与控制器上缺少的方法无关。如果我要创建一个实现IODataRoutingConvention的类,/odata/supplier(1)/product将很好地解析为“~/entityset/key/navigation”。如果我完全绕过我的DTO并返回EF生成的类,则$expand开箱即用。更新2:如果我将Product类更改为以下内容:publicclassProduct{[Key]publicintId{get;放;}公共字符串名称{得到;放;}publicvirtualSupplierSupplier{get;放;}}然后将ProductController更改为:publicclassProductController:ODataController{[HttpGet][Queryable]publicIQueryableGet(){varcontext=newExampleContext();returncontext.EF_Products.Select(x=>newProduct(){Id=x.ProductId,Name=x.ProductName,Supplier=newSupplier(){Id=x.EF_Supplier.SupplierId,Name=x.EF_Supplier.SupplierName}});如果我调用/odata/product,我会得到预期的结果。响应中未返回“供应商”字段的“产品”数组。sql查询生成连接并从Suppliers表中选择,如果不是下一个查询结果,这对我来说很有意义。如果我打电话给/odata/product?$select=Id,我会返回我的期望。但是$select转换为不连接供应商表的SQL查询。/数据/产品?$expand=Product失败并出现不同的错误:“DbIsNullExpression的参数必须引用原语、枚举或引用类型。“如果我将产品控制器更改为以下内容:publicclassProductController:ODataController{[HttpGet][Queryable]publicIQueryableGet(){varcontext=newExampleContext();returncontext.EF_Products.Select(x=>newProduct(){Id=x.ProductId,Name=x.ProductName,Supplier=newSupplier(){Id=x.EF_Supplier.SupplierId,Name=x.EF_Supplier.SupplierName}}).ToList().AsQueryable();}}/odata/product、/odata/product?$select=Id和/odata/product?$expand=Supplier返回正确的结果,但显然.ToList()有点失败。我可以尝试将产品控制器修改为仅在传递$expand查询时调用.ToList(),如下所示:[HttpGet]publicIQueryableGet(ODataQueryOptionsqueryOptions){如果(queryOptions.SelectExpand==null){varresults=context.EF_Products.Select(x=>newProduct(){Id=x.ProductId,Name=x.ProductName,Supplier=newSupplier(){Id=x.EF_Supplier.SupplierId,Name=x.EF_Supplier.SupplierName}});IQueryablereturnValue=queryOptions.ApplyTo(results);将返回值作为IQueryable返回;}else{varresults=context.EF_Products.Select(x=>newProduct(){Id=x.ProductId,Name=x.ProductName,Supplier=newSupplier(){Id=x.EF_Supplier.SupplierId,Name=x.EF_Supplier.SupplierName}}).ToList().AsQueryable();IQueryablereturnValue=queryOptions.ApplyTo(results);将返回值作为IQueryable返回;}}}不幸的是,当我调用/odata/product?$select=Id或/odata/product?当$expand=Supplier时会引发序列化错误,因为returnValue无法转换为IQueryable。如果我调用/odata/product,我可以投射。这里的工作是什么?我是否只需要跳过尝试使用我自己的DTO,或者我可以/应该推出我自己的$expand和$select实现吗?基本问题已在EF6.1.0中修复。请参阅https://entityframework.codeplex.com/workitem/826。您尚未在web-api中设置实体关系。您需要向控制器添加更多方法。我假设以下url不起作用:/odata/product(1)/Supplier这是因为未设置关系。将以下方法添加到您的控制器,我认为它应该可以解决问题://GET/Products(1)/SupplierpublicSupplierGetSupplier([FromODataUri]intkey){varcontext=newExampleContext();产品product=context.EF_Products.FirstOrDefault(p=>p.ID==key);如果(产品==null){抛出新的HttpResponseException(HttpStatusCode.NotFound);}返回产品。供应商;我认为这符合您的命名。根据需要修复它们。有关详细信息,请参阅http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/working-with-entity-relations。您的模型结构非常相似。您应该使用ICollection导航属性而不是IQueryable。这些类型非常不同。不确定这是你的问题,但值得修复。$expand命令仅在控制器操作将MaxExpansionDepth参数添加到Queryable属性(大于0)时才有效。以上就是C#学习教程分享的全部内容:OData$expand、DTO和EntityFramework。如果对你有用,需要进一步了解C#学习教程,希望大家多加关注——【Queryable(MaxExpansionDepth=1)】本文来自网络收藏,不代表立场,如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
