Condividi tramite


Dati

In questa sezione viene illustrato come in WCF RIA Services vengono gestiti gli scenari in cui viene utilizzata la modellazione dei dati, verificata la validità dei dati e garantita la concorrenza dei dati. Quando si fornisce un'interfaccia per l'aggiornamento, l'eliminazione o la creazione di dati dal client di un'applicazione RIA (Rich Internet Application), è spesso necessario modellare alcune relazioni complesse tra i dati e garantire che i dati dell'utente siano validi e ancora utilizzabili con i dati presenti nell'origine dati prima di eseguire il commit delle modifiche dei dati.

In genere, per modellare i dati presenti in un database relazionale viene utilizzato Entity Data Model o LINQ to SQL. Tuttavia, in un progetto RIA Services non è necessario utilizzare un database. È possibile utilizzare qualsiasi tipo di oggetto per archiviare i dati. Il codice nel progetto client che facilita le operazioni sui dati è indipendente dall'origine dati nel senso che non riconosce effettivamente la tecnologia di accesso ai dati o lo schema utilizzato dal livello intermedio.

Relazioni tra i dati

RIA Services fornisce le funzionalità che consentono di interagire con le relazioni complesse tra i dati, ad esempio modelli gerarchici, modelli di ereditarietà polimorfici, modelli di presentazione che consolidano i valori di molte entità e modelli che includono valori di più servizi del dominio. Il modello gerarchico rappresenta una relazione composita padre-figlio, ad esempio Order e OrderDetails, o una relazione ricorsiva, ad esempio un modello Dipendente che include un campo per un oggetto ManagerID che punta a un'altra entità nel modello Dipendente. Per ulteriori informazioni, vedere Gerarchie composizionali.

In un modello di ereditarietà è possibile rappresentare una struttura dei dati che includa un'entità Customer e due entità da essa derivate: PublicSectorCustomer e PrivateSectorCustomer. Utilizzando le operazioni di dominio è possibile eseguire una query e aggiornare i tipi. Per ulteriori informazioni, vedere Ereditarietà nei modelli dati.

In RIA Services V1.0 SP1 è stato aggiunto il supporto dei tipi complessi di non entità. In particolare, il supporto viene fornito per chiamata CODEGEN, metadati, convalida completa, rilevamento delle modifiche, sessioni di modifica e parametri del tipo complesso. Ciò significa che ora è possibile utilizzare i tipi personalizzati, ad esempio Address, come proprietà di entità, parametri o valori restituiti dei metodi DomainService. Per ulteriori informazioni, vedere l'argomento Tipi complessi.

In RIA Services V1.0 SP1 è stato inoltre aggiunto il supporto per la condivisione di un'entità con più servizi del dominio, offrendo la flessibilità necessaria a segmentare le classi DomainService in modo più logico. Per ulteriori informazioni, vedere l'argomento Entità condivise.

In un modello di presentazione è possibile compilare i tipi per il livello di presentazione che non sono collegati direttamente alla struttura delle tabelle dell'origine dati. È possibile ad esempio compilare un tipo di dati denominato CustomerPresentation basato sulle classi di dati per tabelle Customer, CustomerAddress e Address. Nel tipo di presentazione vengono aggregati solo i valori attinenti al livello di presentazione. Se le modifiche vengono apportate nel repository di dati, è possibile modificare solo il tipo di presentazione e non aggiornare il codice dell'applicazione client che interagisce con i dati. RIA Services consente di aggiornare i dati tramite il tipo di presentazione. Per ulteriori informazioni, vedere Modelli di presentazione.

Infine, è possibile che nell'applicazione sia necessario visualizzare dati da una varietà di origini dati o esporre una singola entità a più servizi del dominio. In RIA Services è possibile gestire questo scenario mediante il supporto di riferimenti tra le entità di tipi DomainContext diversi. È possibile ad esempio che in un sito Web di e-commerce sia necessario integrare i dati del sistema di elaborazione degli ordini con i prodotti di un servizio del dominio di terze parti. Per ulteriori informazioni, vedere Procedura dettagliata: condivisione di entità tra più servizi del dominio.

Convalida e annotazioni di dati

Quando si utilizzano le classi di dati nell'applicazione RIA Services , è possibile applicare gli attributi alla classe o ai membri che specificano le regole di convalida e il modo in cui visualizzare i dati nonché impostano le relazioni tra le classi di entità. Lo spazio dei nomi System.ComponentModel.DataAnnotations contiene le classi utilizzate come attributi dei dati. Applicando questi attributi alla classe di dati o al membro, viene centralizzata la definizione dei dati e non è necessario applicare nuovamente le stesse regole in più percorsi. Gli attributi di annotazione dei dati sono organizzati in tre categorie: attributi di convalida, attributi di visualizzazione e attributi di modellazione dei dati. Per ulteriori informazioni, vedere Utilizzo delle annotazioni dati per personalizzare classi di dati e Procedura: convalidare i dati. Per la convalida è possibile utilizzare gli attributi seguenti:

  1. DataTypeAttribute

  2. RangeAttribute

  3. RegularExpressionAttribute

  4. RequiredAttribute

  5. StringLengthAttribute

  6. CustomValidationAttribute

Quando si utilizzano le classi di dati generate automaticamente, ad esempio le classi Entity Data Model o LINQ to SQL, gli attributi non vengono applicati direttamente alle classi generate poiché andrebbero persi alla successiva rigenerazione della classe. Creare invece una classe di metadati per la classe di dati e applicare gli attributi alla classe di metadati. Una classe di metadati è una classe parziale definita dalla classe di dati come tipo di metadati. Per ulteriori informazioni, vedere Procedura: aggiungere classi di metadati.

Nell'esempio seguente viene illustrata una classe di metadati con gli attributi RoundtripOriginalAttribute, RequiredAttribute, StringLengthAttribute e ExcludeAttribute applicati ad alcune proprietà.

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

È possibile creare un attributo di convalida personalizzato aggiungendo un file di codice condiviso e creando in tale file una classe che implementa la logica di convalida. Quando si definisce la classe di convalida personalizzata, è necessario fornire almeno un codice diverso dalle proprietà implementate automaticamente affinché la classe venga generata correttamente nel progetto client. Per un esempio, vedere Procedura: convalidare i dati.

La classe Entity implementa l'interfaccia INotifyDataErrorInfo. Questa interfaccia definisce i membri che forniscono il supporto per la convalida sincrona e asincrona. Con l'interfaccia INotifyDataErrorInfo gli errori di convalida vengono comunicati al progetto client senza generare un'eccezione. Per ulteriori informazioni su INotifyDataErrorInfo, vedere Interfaccia INotifyDataErrorInfo.

È possibile restituire il risultato di un controllo di convalida creando un'istanza della classe ValidationResult.

Nell'esempio seguente viene illustrata una classe di convalida personalizzata che restituisce i risultati tramite un'istanza della classe 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" });
            }
        }
    }
}

Concorrenza di dati

WCF RIA Services supporta la concorrenza ottimistica per assicurare la coerenza dei dati e si basa sugli sviluppatori per fornire la logica per la gestione dei conflitti potenziali che si possono verificare durante l'aggiornamento di un'origine dati. Quando si consente agli utenti di aggiornare o eliminare dati, assicurarsi che i dati dell'origine dati non siano stati modificati da un altro processo.

Per impostazione predefinita, in RIA Services l'entità originale completa non viene passata con i valori modificati al livello di accesso ai dati per verificare la concorrenza dei dati. Al contrario, in RIA Services vengono archiviati e passati nuovamente solo i membri contrassegnati con l'attributo RoundtripOriginalAttribute. Questa implementazione consente di ottimizzare le prestazioni dell'applicazione specificando solo i membri che si desidera partecipino alla verifica della concorrenza.

Il comportamento viene implementato applicando l'attributo alle proprietà in una classe di metadati oppure alla classe di metadati stessa o alle classi di metadati stesse, se si utilizza Entity Framework. Possono essere applicati anche direttamente a proprietà o classi di tipi CLR quando si utilizzano i modelli di dati definiti da POCO. Per ulteriori informazioni, vedere Procedura: aggiungere classi di metadati.

Transazioni

Il framework RIA Services non crea automaticamente le transazioni, ma è possibile aggiungere transazioni esplicite quando si inviano le modifiche. Per creare una transazione esplicita personalizzata, eseguire l'override del metodo Submit. Per ulteriori informazioni, vedere Procedura: aggiungere transazioni esplicite a un servizio del dominio.

Vedere anche

Concetti

Sicurezza per WCF RIA Services