1

最初に説明と要点、次に質問です。そう:

コードAccountView生成されたクラスが

//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; }
}

次に、同じ名前空間 ( Entities)に部分クラスを作成します。

[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(WebApiを使用した最新の6.9.0.0シリーズ、これも最新)で何かを書く、またはしようとします

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 ``http://example.com/service/Accounts?$expand=Company``
//accountSet.HasRequiredBinding(i => i.CompanyId, typeof(Entities.Company));

結果$metadataは次のようになります

<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>

質問:コメントで述べたようにTODO、どのように定義すればよいですか?

  • http://example.com/Accounts?$expand=Companyor http://example.com/Accounts?$Companies?を呼び出すことができるナビゲーション プロパティ。

今私が呼び出すと動作します

  • http://example.com/Accountsまた
  • http://example.com/Accounts(someId)

次に、次のようなことをすると

  • http://example.com/Accounts?$expand=Companies
  • http://example.com/Accounts?$expand=Companyまた
  • http://example.com/Accounts(someId)?$expand=Company

HTTP 400 (?$expand=Companies) またはHTTP 500 (?$expand=Company) で迎えられます。

Containment私はすでに関係を築くことに成功しました。ただし、ルート エンティティを ID で定義する必要があるように見えますが、ルートに「GET」を提供し、オプションで「子リスト」オブジェクトに展開したい (したがって、?$expand= に関するこの質問) .

今のケースでは、expand1 つのエンティティに対して 1 つのオプションではない処理を行っていますが、次に希望するのは、エンティティ (またはこの特定の例に関しては企業) のリストがあるシナリオですが、どうすればこれらを達成できるのでしょうか?シナリオ?最初の常に存在するサブオブジェクトに展開するこのケースでも修正するにはどうすればよいですか?

私のコントローラーは次のように定義されています

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、ビューにいくつかのメタデータを追加し、記事Using $select, $expand, and $value in ASP.NET Web API 2 ODataを模倣することです。これまでのところ成功していません...

<編集 1:いわばプロットが厚くなります。HTTP 500 エラーは、次のような内部例外 (マネージド フレームワーク例外への中断を有効にする必要がありました) から発生します。

タイプ 'System.NotSupportedException' の初回例外が EntityFramework.dll で発生しました

追加情報: 指定された型メンバー 'Company' は、LINQ to Entities ではサポートされていません。初期化子、エンティティ メンバー、およびエンティティ ナビゲーション プロパティのみがサポートされています。

したがって、はい、AccountViewビューであり、テーブルへの直接の外部キー関係はありませんCompany(たまたまテーブルですが、ビューでもある可能性があります)。どうすれば追加できますか?情報によって証明されるように、私はメタデータを追加することですでにトリックを行っていました$metadata。ODataINNER JOINはデータベースに を書き込むだけではありませんか? ここで何か不足していますか?...これは、Company参照を追加した方法に関連しているようで、EFはそれが好きではありません。ODataモデルのみに追加する必要があるようです...

<編集 2:表の定義の大文字と小文字を一致させるために toAccountView CompanyIdを変更しても (少なくとも私が持っている設定では) 違いはないようです。CompanyIDCompany

<edit3:これに関連する別の質問をしました。How to add complex properties on a model built with an ODataConventionModelBuilder from an EF model .

4

2 に答える 2

1

&expand の代わりに $expand を試してください。

于 2014-12-19T21:39:36.607 に答える
0

関連する別の投稿と別のフォーラムからのプッシュについて、これに答えたようです。

例外については、実際、クエリがデータベースにヒットし、そこで定義されていない列を取得しようとしたことが原因でした。詳細については:

コードと回答については、もう 1 つの質問は、 ODataQueryOptions を使用してナビゲーション プロパティを拡張することです。ここで少し拡張されたコードは次のとおりです

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);
于 2014-12-22T14:10:56.990 に答える