2014-12-03 189 views
15

我有一個帶有OData V4的WebAPI 2.2應用程序。另外我使用EF 6.1。OData只讀屬性

在我的實體之一,我有一個計算的屬性:

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 method」爲財產。

我讀了幾篇關於OData中的只讀屬性的帖子(顯然不支持),但我沒有找到一種方法使用OData與計算屬性。

如何克服這種情況的一些建議?

回答

4

你是對的,OData目前不支持read-only properties

但是,它支持read-only entities

或者,您可以通過添加一個setter來欺騙OData,它不會對您的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); 
    } 
} 
+0

我們如何在webapi中做到這一點? – Shivkumar 2014-12-04 08:17:46

+0

我嘗試過用空套裝的技巧。正是我在找什麼。非常感謝你。 – 2015-04-28 07:51:25

+1

@Shivkumar我剛剛在web api中嘗試了這個,並且與空setter一樣工作。 – 2015-04-28 09:32:10

6

現在有這樣做的軟辦法是建立使用註釋客戶端和服務器之間的合同。

Core vocabulary of the V4 standard,有一個這樣的術語:

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

在網頁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))); 

然後在您的數據中,它會看起來像這樣:

​​

通過以上步驟,服務宣告Person實體上的FullName財產由服務計算。然後在POST和PATCH請求的控制器方法中,您可以擁有自己的邏輯,忽略客戶端爲FullName屬性發送的任何值並計算您自己的值。

我不確定您使用的是哪個客戶端。如果您使用OData Client for .NET,我們對獲取註釋值的支持將在我們的下一個版本中發佈。如果您不介意直接使用EdmLib,則已添加註釋值檢索支持。

+0

除了將註釋注入模型右邊之外,目前爲止還沒有支持? – LunicLynx 2015-09-02 15:42:02

0

您可以使用數據庫計算屬性而不是類計算屬性。

This article describes EF and database computed properties.與我的文章相比,我在示例代碼中看到的一個區別是您的屬性中沒有任何setter。如果你設置你的財產使用自動存取器與私定

public string FullName { 
    get; 
    private set; 
} 

然後在數據庫中創建列的計算列。

ALTER TABLE dbo.Users ADD FullName AS FirstName + ' ' + LastName 

作爲額外的加號,您可以使用odata和Linq查詢此屬性。

+0

鏈接的文章根本沒有提及OData。 – 2017-08-03 18:59:19

+0

@CarlBussema - 你的正確。我重新寫了這篇文章,以免誤導。 – 2017-08-03 20:45:16