如何定义一个可选的导航属性(?$展开;)在code?

编程入门 行业动态 更新时间:2024-10-27 07:31:46
本文介绍了如何定义一个可选的导航属性(?$展开;)在code?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

首先,解释和要点,那么问题。所以:

First the explanation and the gist, then the question. So:

比方说,我有一个观点 AccountView 在EF定义(6.1.1)数据库第一(EDMX),以便code生成的类是

Let's say I have a view AccountView defined in EF (6.1.1) database first (edmx) so that the code-generated class is

//This class is generated from a view by EF (edmx)... public partial class AccountView { public System.Guid Id { get; set; } public int CompanyId { get; set; } }

然后,我创建了相同的命名空间部分类(实体)的

[MetadataType(typeof(AccounViewMetaData))] public partial class AccounView { //This is added here explicitly. AccountView itself exposes just //a naked key, CompanyId. public virtual Company Company { get; set; } //This is just in case... public class AccounViewDomainMetaData { //This is to add a navigation property to the OData $metadata. How to do this //in WebApiConfig? See as follows... [ForeignKey("Company")] public int CompanyId { get; set; } } }

//This is an EF generated class one from an edmx..- public partial class Company { public Company() { } public int CompanyID { get; set; } public string Name { get; set; } }

然后在 WebApiConfig 我写,或尝试,在OData的V4的东西(最新,6.9.0.0系列的WebAPI,最新的也有)如下:

And then in WebApiConfig I Write, or try to, something in OData v4 (the newest, 6.9.0.0 series with WebApi, the newest also) as follows

builder.EntitySet<Entities.Company>("Companies"); var accountSet = builder.EntitySet<Entities.AccountView>("Accounts"); accountSet.EntityType.HasKey(i => i.Id); //EF has hard time recognizing primary keys on database first views... //TODO: How should I define the required binding so that I could "?$expand=Company" //as such as ``example/service/Accounts?$expand=Company`` //accountSet.HasRequiredBinding(i => i.CompanyId, typeof(Entities.Company));

生成的 $元像

<schema> <EntityType Name="Company"> <Key> <PropertyRef Name="CompanyID"/> </Key> <Property Name="CompanyID" Type="Edm.Int32" Nullable="false"/> <Property Name="Name" Type="Edm.String"/> </EntityType> <EntityType Name="AccountView"> <Key> <PropertyRef Name="Id"/> </Key> <Property Name="Id" Type="Edm.Guid" Nullable="false"/> <Property Name="CompanyId" Type="Edm.Int32" Nullable="false"/> <NavigationProperty Name="Company" Type="Entities.Company" Nullable="false"/> </EntityType> </Schema>

问题(S):正如 TODO 评论中提及,我应该如何定义

Question(s): As mentioned in the TODO comment, how should I define

  • 的导航属性,这样我可以打电话给 example/Accounts?$expand=Company 或的http://例子.COM /账户?$公司?
  • A navigational property so that I could call example/Accounts?$expand=Company or example/Accounts?$Companies?

现在它的工作原理,如果我称之为

Now it works if I call

  • example/Accounts 或
  • example/Accounts(someId)
  • example/Accounts or
  • example/Accounts(someId)

然后,如果我做这样的事情。

Then if I do something like

  • example/Accounts?$expand=Companies
  • example/Accounts?$expand=Company 或
  • example/Accounts(someId)?$ =拓展公司
  • example/Accounts?$expand=Companies
  • example/Accounts?$expand=Company or
  • example/Accounts(someId)?$expand=Company

我得到映入眼帘的 HTTP 400 (?$展开;公司)或 HTTP 500 (?$ =拓展公司)。

I get greeted by HTTP 400 (?$expand=Companies) or HTTP 500 (?$expand=Company).

我会成功,但创建一个遏制关系了。它看起来像,不过,它需要具有由一个ID定义的根实体,而我想提供GET为根和可选扩展到子榜对象(因此这个问题呢?$ =扩展)

I succeeded with creating a Containment relationship already. It looks like, though, it requires having the root entity defined by an ID, whereas I'd like to provide "GET" to the root and optionally expand to a "child list" objects (hence this question about ?$expand=).

现在的情况是有一个非可选的展开做了一个实体,但我怀疑,我想未来的事情已经是那里的列表的场景实体(或公司在这个具体的例子而言),但我怎么能实现这些场景?如何修复即使这种情况下的扩展应用于第一总是存在的子对象?

Now the case is having one non-optional expand done for one entity, but I suspect the next thing I'd like have is a scenario where there's a list of entities (or companies in terms of this specific example) but how could I achieve these scenarios? How to fix even this case of expanding to the first always existing sub-object?

我的控制器被定义如下

public class AccountsController: ODataController { [EnableQuery] public IHttpActionResult Get() { try { //This context here is a EF entities model (generated from an edmx)... return Ok(Context.AccountView); } catch(Exception ex) { return InternalServerError(); } } [EnableQuery] public IHttpActionResult Get([FromODataUri]Guid key) { try { return Ok(SingleResult.Create(Context.AccountView.Where(a => a.Id == key))); } catch (Exception ex) { return InternalServerError(ex); } } }

什么我基本上试图做的是添加一些更多的元数据数据库第一,EDMX,观点和模拟天生的文章使用$选择,$扩大,并在的ASP.NET Web API的OData 2 $ 的价值。迄今没有成功...

What I'm basically trying to do is to add some more metadata to database first, edmx, views and mimick the article Using $select, $expand, and $value in ASP.NET Web API 2 OData. Thus far with no success...

&LT;编辑1:越来越复杂了,可以这么说。 HTTP 500错误来自内部异常(我不得不把打破托管框架例外),上面写着

<edit 1: The plot thickens, so to speak. The HTTP 500 error comes from an internal exception (I had to turn on breaking to managed framework exceptions) that says

System.NotSupportedException类型的第一次机会异常出现在EntityFramework.dll

A first chance exception of type 'System.NotSupportedException' occurred in EntityFramework.dll

其他信息:指定的类型成员公司不支持LINQ到实体。只有初始化,实体成员和实体导航属性都支持。

Additional information: The specified type member 'Company' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

所以,是的, AccountView 是一个视图,它没有直接的外键关系公司表(这恰好是一个表,但也可以是一个视图太)。我怎么可能去增加一个?我虽然添加元数据的伎俩已经由 $元信息作为证明。不只是OData的写 INNER JOIN 在数据库中?我失去了一些东西在这里? ...这似乎与我添加了公司引用和EF不喜欢这样的方式。它看起来我应该去了解它添加到OData的模型仅仅...

So, yes, AccountView is a view and it does not have a direct foreign key relation to Company table (which just happens to be a table, but it could be a view too). How could I go to add one? I though adding metadata did the trick already, as evidenced by $metadata information. Doesn't OData just write an INNER JOIN in the database? Am I missing something here? ... This seem to be related to the way I added the Company reference and EF doesn't like that. It looks I should go about adding it to the OData model only...

&LT;编辑2:这似乎并没有发挥作用(至少不符合我的设置),如果我更改 AccountView CompanyId 到 CompanyID 相匹配的外壳,在公司定义的表。

<edit 2: It doesn't seem to make a difference (at least not with the setting I have) if I change the AccountView CompanyId to CompanyID to match the casing that of the definition in Company table.

&LT; EDIT3:我问另外一个相关的问题这一点,How在从EF模型与ODataConventionModelBuilder建立了一个模型添加复杂的属性。

<edit3: I asked another, related question to this, How to add complex properties on a model built with ODataConventionModelBuilder from an EF model.

推荐答案

这看起来我这人回答为相关的另一篇文章和小从另一个论坛上推。

It looks I got this one answered as to related another post and little pushing from another forum.

关于异常,事实上,它是由该查询击中到数据库并尝试检索它们没有定义的列引起的。欲了解更多信息:

About the exception, indeed, it was caused by the query hitting to the database and trying to retrieve columns which aren't defined there. For more information:

  • The指定型部件中不LINQ支持实体。只有初始化,实体成员和实体导航属性都支持
  • EF 4:指定类型的成员'*'在LINQ是不支持的实体
  • The specified type member is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported
  • EF 4: The specified type member '*' is not supported in LINQ to Entities

然后作为code和答案,另一个问题是,Expanding导航性能与ODataQueryOptions 。在code有点这里增加如下:

Then as for the code and answer, the other question is Expanding navigation properties with ODataQueryOptions. The code a bit augmented here is as follows

public async Task<IHttpActionResult> Get(ODataQueryOptions<T> options) { IQueryable<T> tempQuery = Context.AccountView; IQueryable<T result = tempQuery; if(options.SelectExpand != null) { if(options.Filter != null) { tempQuery = options.Filter.ApplyTo(tempQuery, new ODataQuerySettings()) as IQueryable<T>; } /* Other options that should go to the DB level... */ //The results need to be materialized, or otherwise EF throws a //NotSupportedException due to columns and properties that aren't in the DB... result = (await tempQuery.ToListAsync()).AsQueryable(); //Do here the queries that can't be hit straight by the queries. E.g. //navigation properties not defined in EF views (that can't be augmented)... //E.g. get the company here. //This is needed to that OData formatter knows to render navigation links too. Request.ODataProperties().SelectExpandClause = options.SelectExpand.SelectExpandClause; } return Ok(result);

更多推荐

如何定义一个可选的导航属性(?$展开;)在code?

本文发布于:2023-11-26 12:26:43,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1633928.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:可选   属性   定义   code

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!