Share via


資料

本節將說明 WCF RIA Services 如何處理與模型化資料、檢查資料有效性和確保資料並行有關的情況。提供用於從豐富網際網路應用程式 (RIA) 更新、刪除或建立資料的介面時,經常需要模型化一些複雜的資料關聯性,並確保在送出資料變更之前使用者的資料是有效的,而且依然保持與資料來源的資料一致。

通常,您會使用實體資料模型或 LINQ to SQL 來模型化已存在於關聯式資料庫中的資料,但不需要在 RIA Services 專案中使用資料庫。您可以使用任何型別的物件來儲存資料。從實際上對資料存取技術或中介層使用的結構描述未知的角度來看,在用戶端專案中有助於資料作業的程式碼與資料來源無關。

資料關聯性

RIA Services 提供的功能可讓您與複雜的資料關聯性 (例如階層式模型、多形繼承模型、合併許多實體之值的展示模型和包含多個網域服務之值的模型) 進行互動。階層式模型代表父子複合關聯性 (例如 OrderOrderDetails) 或遞迴關聯性 (例如一個 Employee 模型,內含指向 Employee 模型中另一個實體之 ManagerID 的欄位)。如需詳細資訊,請參閱複合階層

在階層式模型中,您可以將內含 Customer 實體及其衍生之兩個實體 (PublicSectorCustomerPrivateSectorCustomer) 的資料結構呈現出來。網域作業可用來查詢及更新型別。如需詳細資訊,請參閱資料模型中的繼承

RIA Services V1.0 SP1 中已加入非實體複雜型別的支援。特別是,提供程式碼產生、中繼資料、深層驗證、變更追蹤、編輯工作階段和複雜型別參數的支援。這表示自訂型別 (例如 Address) 現在可以當做實體屬性或是 DomainService 方法的參數或傳回值。如需詳細資訊,請參閱複雜型別主題。

RIA Services V1.0 SP1 中已加入實體與多個網域服務共用的支援。這項支援使分割 DomainService 類別所需的彈性更具邏輯意義。如需詳細資訊,請參閱共用的實體主題。

在展示模型中,您可以為展示層建置未直接繫結至資料來源資料表之結構的型別。例如,您可以建立名為 CustomerPresentation 的資料型別,以 Customer、CustomerAddress 和 Address 資料表的資料類別為基礎。在展示型別中只會彙總與展示層有關的值。如果資料儲存機制發生變更,您只能變更展示型別,不能更新與資料互動的程式碼用戶端應用程式。RIA Services 可讓您透過展示型別更新資料。如需詳細資訊,請參閱展示模型

最後,您可能需要在應用程式中顯示來自各種資料來源的資料,或向一個以上的網域服務公開單一實體。RIA Services 因為支援不同 DomainContext 型別的實體之間的參考,因此可適用於這種情況。例如,電子商務網站可能需要整合訂單處理系統的資料與協力廠商網域服務的產品。如需詳細資訊,請參閱逐步解說:在多個網域服務中共用實體

資料附註和驗證

在 RIA Services 應用程式中使用資料類別時,您可以將屬性套用至類別或成員,這些屬性可指定驗證規則、指定資料的顯示方式和設定實體類別間的關聯性。System.ComponentModel.DataAnnotations 命名空間包含可做為資料屬性的類別。在資料類別或成員上套用這些屬性,即可集中資料定義,而不必在多個位置重新套用相同規則。資料附註分成三類:驗證屬性、顯示屬性和資料模型化屬性。如需詳細資訊,請參閱使用資料附註自訂資料類別HOW TO:驗證資料。您可以為驗證使用下列屬性:

  1. DataTypeAttribute

  2. RangeAttribute

  3. RegularExpressionAttribute

  4. RequiredAttribute

  5. StringLengthAttribute

  6. CustomValidationAttribute

使用自動產生的資料類別 (例如實體資料模型或 LINQ to SQL 類別) 時,不會直接套用屬性至產生的類別,因為屬性會在下次重新產生類別時遺失。而是會建立資料類別的中繼資料,然後套用屬性至中繼資料類別。中繼資料類別是一種從資料類別被指定為中繼資料型別的部分類別。如需詳細資訊,請參閱 HOW TO:加入中繼資料類別

下列範例會顯示 RoundtripOriginalAttributeRequiredAttributeStringLengthAttributeExcludeAttribute 屬性 (Attribute) 套用至某些屬性 (Property) 的中繼資料類別。

<MetadataTypeAttribute(GetType(Address.AddressMetadata))>  _
Partial Public Class Address
    
    Friend NotInheritable Class AddressMetadata
        
        'Metadata classes are not meant to be instantiated.
        Private Sub New()
            MyBase.New
        End Sub
        
        Public AddressID As Integer

        <Required()> _
        <StringLength(60)> _
        <RoundtripOriginal()> _
        Public AddressLine1 As String

        <RoundtripOriginal()> _
        Public AddressLine2 As String

        <Required()> _
        <StringLength(30)> _
        <RoundtripOriginal()> _
        Public City As String

        <RoundtripOriginal()> _
        Public CountryRegion As String
        
        Public CustomerAddresses As EntityCollection(Of CustomerAddress)

        <RoundtripOriginal()> _
        Public ModifiedDate As DateTime

        <Required()> _
        <RoundtripOriginal()> _
        Public PostalCode As String

        <Exclude()> _
        Public rowguid As Guid

        <RoundtripOriginal()> _
        Public StateProvince As String
    End Class
End Class
[MetadataTypeAttribute(typeof(Address.AddressMetadata))]
public partial class Address
{

    internal sealed class AddressMetadata
    {
        // Metadata classes are not meant to be instantiated.
        private AddressMetadata()
        {
        }

        public int AddressID { get; set; }

        [Required]
        [StringLength(60)]
        [RoundtripOriginal]
        public string AddressLine1 { get; set; }

        [RoundtripOriginal]
        public string AddressLine2 { get; set; }

        [Required]
        [StringLength(30)]
        [RoundtripOriginal]
        public string City { get; set; }

        [RoundtripOriginal]
        public string CountryRegion { get; set; }

        public EntityCollection<CustomerAddress> CustomerAddresses { get; set; }

        [RoundtripOriginal]
        public DateTime ModifiedDate { get; set; }

        [Required]
        [RoundtripOriginal]
        public string PostalCode { get; set; }

        [Exclude]
        public Guid rowguid { get; set; }

        [RoundtripOriginal]
        public string StateProvince { get; set; }
    }
}

加入共用程式碼檔並在其中建立實作驗證邏輯的類別,即可建立自訂驗證屬性。當您定義自訂驗證類別時,至少必須提供一些程式碼,而不是用戶端專案中正確產生之類別的自動實作屬性。如需範例,請參閱 HOW TO:驗證資料

Entity 類別會實作 INotifyDataErrorInfo 介面。這個介面會定義提供同步和非同步驗證支援的成員。透過 INotifyDataErrorInfo 介面,驗證錯誤會直接傳遞到用戶端專案,而不會引發例外狀況。如需 INotifyDataErrorInfo 的詳細資訊,請參閱 INotifyDataErrorInfo 介面

建立 ValidationResult 類別的執行個體,即可傳回驗證檢查的結果。

下列範例示範會透過 ValidationResult 類別的執行個體傳回結果的自訂驗證類別。

Imports System
Imports System.ComponentModel.DataAnnotations

Public Module GenderValidator
    Public Function IsGenderValid(ByVal gender As String, ByVal context As ValidationContext) As ValidationResult
        If gender = "M" OrElse gender = "m" OrElse gender = "F" OrElse gender = "f" Then
            Return ValidationResult.Success
        Else
            Return New ValidationResult("The Gender field only has two valid values 'M'/'F'", New String() {"Gender"})
        End If
    End Function
End Module
using System;
using System.ComponentModel.DataAnnotations;

namespace HRApp.Web
{
    public static class GenderValidator
    {
        public static ValidationResult IsGenderValid(string gender, ValidationContext context)
        {
            if (gender == "M" || gender == "m" || gender == "F" || gender == "f")
            {
                return ValidationResult.Success;
            }
            else
            {
                return new ValidationResult("The Gender field only has two valid values 'M'/'F'", new string[] { "Gender" });
            }
        }
    }
}

資料並行

WCF RIA Services 支援開放式並行存取以確保資料一致性,而且依靠開發人員提供邏輯以處理更新資料來源時可能會發生的潛在衝突。當使用者可以更新或刪除資料時,您應該確保沒有其他處理序已經變更資料來源中的資料。

根據預設,RIA Services 不會將整個原始實體連同變更的值傳遞給資料存取層來檢查資料的並行。相反地,RIA Services 只會儲存並傳回那些標記著 RoundtripOriginalAttribute 屬性的成員。這個實作可讓您最佳化應用程式的效能,其方式是只指定您希望參與並行存取檢查的成員。

使用 Entity Framework 時,藉由將屬性 (Attribute) 套用至中繼資料類別中的屬性 (Property)、一個或多個中繼資料類別本身,實作此行為。使用 POCO 定義資料模型時,它們也可以直接套用至 CLR 型別的屬性或類別。如需詳細資訊,請參閱 HOW TO:加入中繼資料類別

交易

RIA Services 架構並不會自動建立交易,但您可以在送出變更時加入明確交易。為了建立您自己的明確交易,您會覆寫 Submit 方法。如需詳細資訊,請參閱 HOW TO:將明確交易加入至網域服務

另請參閱

概念

WCF RIA Services 的安全性