ODataV4を使用したWebAPI2.2アプリケーションがあります。また、EF6.1を使用しています。
私のエンティティの1つに、計算されたプロパティがあります。
public class Person {
public string FirstName { get; set; }
public string LastName { get; set; }
// Calculated Property - No setter
public string FullName {
get {
return FirstName + " " + LastName;
}
}
計算されたプロパティをクライアントに提供するには、ODataモデルに登録する必要があります
public static IEdmModel GetModel()
{
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.Namespace = "NavigationServices";
builder.EntityType<Person>;
builder.EntityType<Person>().Property(a => a.FullName); // Calculated Property
....
return builder.GetEdmModel();
}
したがって、クライアント側でデータを取得すると、すべてのオブジェクトにCalculatedプロパティがあります。
ただし、新しい要素を作成(POST)または既存の要素を更新(PUT)しようとすると、アクションが要素を認識せず、プロパティの「setメソッド」が見つからないというエラーが生成されます。
ODataの読み取り専用プロパティ(明らかにサポートされていない)に関するいくつかの投稿を読みましたが、計算されたプロパティでODataを使用する方法が見つかりません。
この状況を克服する方法についてのアドバイスはありますか?
これを行うためのソフトな方法があります。これは、注釈を使用してクライアントとサーバー間の契約を構築することです。
V4標準のコアボキャブラリー には、次のような用語があります。
<Term Name="Computed" Type="Core.Tag" DefaultValue="true" AppliesTo="Property">
<Annotation Term="Core.Description" String="A value for this property is generated on both insert and update"/>
</Term>
Web API ODataのWebConfig.csで、このような注釈をプロパティに追加するコードを記述します。
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
var model = builder.GetEdmModel() as EdmModel;
model.SetVocabularyAnnotation(
new EdmAnnotation(model.EntityContainer.FindEntitySet("People").EntityType().FindProperty("FullName"),
new EdmTerm("Org.OData.Core.V1", "Computed", EdmPrimitiveTypeKind.Boolean),
new EdmBooleanConstant(true)));
次に、データでは、次のようになります。
<Annotations Target="V4Service.Models.Person/FullName">
<Annotation Term="Org.OData.Core.V1.Computed" Bool="true"/>
</Annotations>
上記の手順を通じて、サービスはFullName
エンティティのPerson
プロパティがサービスによって計算されることをアドバタイズします。次に、POSTおよびPATCHリクエストのコントローラーメソッドで、クライアントからFullName
プロパティに送信された値を無視する独自のロジックを作成し、独自のロジックを計算できます。
使用しているクライアントがわかりません。 OData Client for .NET を使用している場合、アノテーション値の取得のサポートは次のリリースで行われます。 EdmLib を直接使用してもかまわない場合は、アノテーション値の取得サポートがすでに追加されています。
確かに、現時点ではOData
はread-only properties
をサポートしていません。
ただし、read-only entities
をサポートします。
または、OData
に何もしないsetter
を追加して、property
をだますことができます。
public string FullName
{
get
{
return FirstName + " " + LastName;
}
set
{
// do nothing
}
}
これは、entity
を読み取り専用として設定する方法です。
public class Northwind : DataService<NorthwindEntities>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Customers", EntitySetRights.AllRead);
}
}
クラス計算プロパティの代わりに、データベース計算プロパティを使用できます。
この記事では、EFとデータベースで計算されたプロパティについて説明します。 サンプルコードでこの記事と比較して見られる違いの1つは、プロパティにセッターがないことです。プライベートセットでオートアクセサーを使用するようにプロパティを設定した場合
public string FullName {
get;
private set;
}
次に、データベースに計算列として列を作成します。
ALTER TABLE dbo.Users ADD FullName AS FirstName + ' ' + LastName
追加のプラスとして、odataとLinqを使用してこのプロパティに対してクエリを実行できます。