Definiowanie modeli danych dla aplikacji Fabric

Fabric Apps używa dekoratorów języka TypeScript do definiowania modeli danych, które generują tabele bazy danych i interfejsy API. Każda jednostka jest definiowana jako klasa ozdobiona elementem @entity(), dodaj dekoratory pól dla typów danych i mapuj relacje między jednostkami.

Aby uzyskać wskazówki dotyczące autoryzacji i kontroli dostępu, zobacz Definiowanie uprawnień do danych.

Wymagania wstępne

  • Projekt Fabric Apps utworzony za pomocą npm create @microsoft/rayfin@latest lub zainicjowany przy użyciu npx rayfin init.
  • Podstawowa wiedza na temat klas i dekoratorów języka TypeScript.

Definiowanie jednostki

Aby utworzyć model danych, dodaj @entity() dekorator do klasy TypeScript. Następnie zaimportuj wymagane dekoratory z elementu @microsoft/rayfin-core:

import { entity, uuid, text, date } from '@microsoft/rayfin-core';

@entity()
export class Todo {
  @uuid() id!: string;
  @text() title!: string;
  @text({ optional: true }) description?: string;
  @date() createdAt!: Date;
  @date() updatedAt!: Date;
}

Ta jednostka generuje tabelę Todo z kolumnami dla id, , title, descriptioncreatedAt, i updatedAt.

Klucze podstawowe

Każda jednostka używa pola UUID string o nazwie id jako klucza podstawowego. Jeśli nie deklarujesz jawnie id, Fabric Apps doda ją do schematu automatycznie.

  • Pole id jest opcjonalne podczas operacji tworzenia — serwer generuje identyfikator UUID, jeśli go pominięto.
  • Jeśli wolisz identyfikatory generowane przez klienta, możesz podać własny identyfikator UUID w czasie tworzenia.
  • Złożone klucze podstawowe i niestandardowe nazwy kluczy nie są obsługiwane.
@entity()
export class Note {
  @uuid() id!: string;  // UUID primary key, auto-generated when omitted
  @text() title!: string;
  @text() content!: string;
}

Obsługiwane typy danych

Użyj tych dekoratorów, aby zdefiniować typy pól:

Dekorator Typ Opis
@uuid() ciąg Unikatowe pole identyfikatora.
@text() ciąg Pole tekstowe z opcjonalnymi ograniczeniami długości.
@int() number Pole liczb całkowitych.
@decimal() number Pole dziesiętne lub liczbowe.
@boolean() boolean Pole prawda lub fałsz.
@date() Data Pole daty i godziny, jest serializowane z ciągów w formacie ISO lub obiektów Date.
@email() ciąg Pole tekstowe z weryfikacją wiadomości e-mail.
@set() ciąg Wyliczony zestaw literałów ciągu.

Przykład z wieloma typami

import { entity, uuid, text, int, decimal, boolean, date, set } from '@microsoft/rayfin-core';

@entity()
export class Product {
  @uuid() id!: string;
  @text() name!: string;
  @decimal() price!: number;
  @int() stockQuantity!: number;
  @boolean() isAvailable!: boolean;
  @date() createdAt!: Date;
  @set('draft', 'published', 'archived') status!: 'draft' | 'published' | 'archived';
}

Modyfikatory typów

Dodaj modyfikatory do dekoratorów pól, aby skonfigurować walidację i ograniczenia:

Modyfikator Opis
{ optional: true } Zezwalaj na wartości NULL. Pola są domyślnie wymagane.
{ unique: true } Dodaj unikatowe ograniczenie.
{ default: value } Ustaw wyrażenie wartości domyślnej.
{ max: n }, { min: n } Ograniczenia długości ciągu (maksymalna i minimalna liczba znaków).
{ min: n }, { max: n } Ograniczenia wartości liczbowych.

Uwaga / Notatka

Opcjonalny znacznik TypeScript (? po nazwie właściwości) ma wpływ tylko na statyczny typ TypeScript. Nie powoduje, że kolumna bazy danych może przyjmować wartość NULL. Aby pole mogło przyjmować wartość null, dodaj element { optional: true } do dekoratora. Użyj !, aby zadeklarować, że wymagane pole jest inicjalizowane przez framework.

Przykład z modyfikatorami

@entity()
export class User {
  @uuid() id!: string;
  @email({ unique: true }) email!: string;
  @text({ min: 3, max: 50 }) username!: string;
  @text({ optional: true, max: 500 }) bio?: string;
  @int({ min: 0, max: 150 }) age!: number;
  @boolean({ default: false }) isVerified!: boolean;
}

Definiowanie relacji

Dekoratory @one() i @many() służą do definiowania właściwości nawigacji między jednostkami. Fabric Apps automatycznie generuje kolumny kluczy obcych podczas definiowania relacji.

  • Jeden do wielu – użyj @many() w elemencie nadrzędnym i @one() w elemencie podrzędnym.
  • Wiele do jednego – użyj @one() w elemencie podrzędnym, aby odwołać się do elementu nadrzędnego.
  • Relacje wiele-do-wielu nie są obsługiwane — zamiast tego użyj jawnej jednostki sprzężenia.

Przykład relacji jeden do wielu

import { entity, uuid, text, date, one, many } from '@microsoft/rayfin-core';

@entity()
export class Notebook {
  @uuid() id!: string;
  @text() name!: string;
  @date() createdAt!: Date;
  @many(() => Note) notes?: Note[];
}

@entity()
export class Note {
  @uuid() id!: string;
  @text() title!: string;
  @text() content!: string;
  @date() createdAt!: Date;
  @text() notebook_id!: string;
  @one(() => Notebook) notebook?: Notebook;
}

Gdy zdefiniujesz @one(() => Notebook) dla encji Note, aplikacje Fabric automatycznie utworzą kolumnę klucza obcego notebook_id. Zadeklaruj pole klucza obcego jawnie tylko wtedy, gdy planujesz go odczytać lub ustawić w kodzie aplikacji.

Konwencja nazewnictwa kluczy obcych

Podczas definiowania pola klucza obcego należy użyć {property}_id konwencji nazewnictwa:

@entity()
export class Note {
  @uuid() id!: string;
  @text() notebook_id!: string;      // Foreign key field
  @one(() => Notebook) notebook?: Notebook;  // Navigation property
}

Niestandardowe nazwy kluczy obcych (foreignKey, targetKey opcje) nie są obsługiwane.

Referencyjne encje systemowe

Fabric Apps nie obsługuje relacji @one() wskazujących jednostki systemowe, takie jak wbudowana jednostka USER. Aby powiązać wiersz z zalogowanym użytkownikiem, dodaj zwykłe pole user_id typu @text() i wypełnij je na podstawie claimów uwierzytelniających (zwykle claims.sub):

@entity()
export class Task {
  @uuid() id!: string;
  @text() title!: string;
  @text() user_id!: string;  // System user ID from claims.sub
}

Filtruj wiersze według user_id w zasadach ról, aby egzekwować dostęp na poziomie użytkownika.

Zarejestruj encje w schemacie

Dodaj wszystkie klasy encji do rayfin/data/schema.ts, aby klient mógł wygenerować serwery proxy GraphQL:

import type { Note } from './Note.js';
import type { Notebook } from './Notebook.js';

export type NotesAppSchema = {
  Note: Note;
  Notebook: Notebook;
};

Zaktualizuj ten typ za każdym razem, gdy utworzysz nową jednostkę.

Zastosuj zmiany schematu

Po zdefiniowaniu lub zmodyfikowaniu jednostek zastosuj zmiany do bazy danych:

  1. Wdróż zaktualizowany schemat w Fabric:

    npx rayfin up db apply
    
  2. Jeśli zmiana schematu obejmuje operacje destruktywne (porzucanie kolumn, zmienianie nazw tabel), interfejs wiersza polecenia ostrzega Cię i odmawia kontynuowania. Użyj --force polecenia , aby zastąpić kontrolę bezpieczeństwa:

    npx rayfin up db apply --force
    

Uwaga / Notatka

Użycie --force może spowodować utratę danych. Przed kontynuowaniem przejrzyj wymienione operacje uważnie.

Najlepsze rozwiązania

  • Definiuj pola kluczy obcych tylko wtedy, gdy trzeba je odczytywać lub ustawiać w kodzie — Fabric Apps generuje je automatycznie na podstawie dekoratorów nawigacyjnych.
  • Użyj importów względnych z rozszerzeniami .js w plikach encji, aby wygenerowany kod JavaScript ESM był poprawnie rozwiązywany.
  • Aby uzyskać informacje o wzorcach autoryzacji i dostępie opartym na rolach, zobacz Definiowanie uprawnień do danych.

Troubleshooting

Brakujące relacje

Jeśli relacje nie są wyświetlane w interfejsie API, sprawdź, czy:

  • Dekorator nawigacji (@one() lub @many()) jest obecny.
  • Podmiot jest zarejestrowany w rayfin/data/schema.ts.