Modellierung einer Datenbankstruktur für mehrere Benutzertypen und deren Kontaktinformationen

10

Ich entwerfe eine Datenbank, in der Benutzer unterschiedlicher Typen gespeichert werden. Überwiegend (aber nicht ausschließlich) werden sie Schauspieler, Regisseure und Autoren sein. Derzeit sind nur vier Benutzertypen relevant. Es besteht die Möglichkeit von außen, dass sich diese Zahl erhöht, aber die Wahrscheinlichkeit ist gering - und in einem solchen Fall wäre es eine sehr kleine Zahl.

Der Plan ist , eine haben usersTabelle verantwortlich ziemlich ausschließlich in die Website anmelden ( name, emailund passwordSpalten plus ein oder zwei andere, wie , ob sie genehmigt wurden, und updated_at) und zusätzliche Tabellen für jede der jeweiligen Benutzer tippt , dass jeder haben ihre eigenen eindeutigen Spalten. Zum Beispiel haben nur Schauspieler eine Ethnizitätsspalte, nur Regisseure eine Biospalte und nur Schriftsteller müssten ihren Standort angeben. Da ich jedoch noch nie eine Datenbank dieser Komplexität verwaltet habe, frage ich mich, wie ich einige Aspekte organisieren kann:

Erstens können Benutzer ein beliebiger oder eine beliebige Kombination der oben genannten Typen sein. Ich verstehe also, dass ich so etwas wie (zum Beispiel) eine director_userTabelle mit director_idund user_idSpalten benötigen würde . Wäre dies dann ausreichend, um alle Benutzer nach Rollentyp usw. filtern zu können?

Zweitens haben die meisten Benutzer die Möglichkeit, ein Twitter-Profil und eine Telefonnummer zu wählen. Und alle Schauspieler müssen mindestens eine URL für eines ihrer anderen Online-Schauspielerprofile angeben. Derzeit gibt es drei, die sie einschließen können, aber diese Anzahl kann sich erhöhen. Habe ich Recht, wenn ich davon ausgehe, dass eine separate Tabelle für jedes der möglichen Profile / Kontaktmethoden ein optimaler Weg ist, um Daten zu organisieren?

Verismus
quelle

Antworten:

14

Nach meiner Interpretation Ihrer Beschreibung des interessierenden Geschäftskontexts handelt es sich um eine Struktur vom Supertyp-Subtyp 1 , bei der (a) Schauspieler , Regisseur und Autor Entitätssubtypen von (b) Person , deren Entitätstyp und (c) sind. Diese Untertypen schließen sich nicht gegenseitig aus.

Wenn Sie auf diese Weise eine relationale Datenbank erstellen möchten, die ein solches Szenario genau widerspiegelt - und daher erwarten, dass es als solches funktioniert -, sind Ihre folgenden Erläuterungen zu den vorherigen Punkten von großer Bedeutung, da sie Auswirkungen auf haben sowohl (1) die konzeptionelle als auch (2) die logische Darstellungsebene der betreffenden Datenbank:

  • […] Zusätzliche Tabellen für jeden der jeweiligen Benutzertypen, die jeweils einen eigenen Satz von Spalten haben.

  • […] Es gibt nur vier Benutzertypen, die relevant sind. Es besteht die Möglichkeit von außen, dass sich diese Zahl erhöht, aber die Wahrscheinlichkeit ist gering - und in einem solchen Fall wäre es eine sehr kleine Zahl.

Ich werde in den folgenden Abschnitten auf all diese Aspekte und einige andere kritische Faktoren eingehen.

Geschäftsregeln

Um zunächst das entsprechende konzeptionelle Schema zu definieren, das als nachfolgende Referenz verwendet werden kann, damit Sie es anpassen können, um sicherzustellen, dass es den genauen Informationsanforderungen entspricht, habe ich einige Geschäftsregeln formuliert, die von besonderer Bedeutung sind:

  • Eine Person kann eine, zwei oder drei (dh eins zu alle) Rollen 2 ausführen . Mit anderen Worten kann eine Person sein
    • ein Schauspieler und
    • ein Direktor und
    • ein Schriftsteller .
  • Eine Person kann sich über ein Benutzerprofil von null oder eins anmelden .
  • Ein Akteur stellt eine, zwei oder drei URLs bereit 3 .
  • Ein Schauspieler wird nach einer ethnischen Zugehörigkeit gruppiert .
  • Eine ethnische Zugehörigkeit gruppiert null, eins oder viele Akteure .
  • Ein Writer befindet sich an einem Ort .
  • Ein Standort ist die Basis von Null-Eins- Autoren oder mehr .

Expository IDEF1X-Diagramm

Dann habe ich das in Abbildung 1 gezeigte IDEF1X 4- Diagramm erstellt, in dem alle obigen Formulierungen zusammen mit anderen Regeln zusammengefasst sind, die relevant erscheinen:

Abbildung 1 - IDEF1X-Diagramm für Personenrollen und Kontaktdetails im Kino

Wie gezeigt, hat der Personensupertyp (i) eine eigene Box, (ii) besitzt die Eigenschaften oder Attribute, die für alle Subtypen gelten, und (iii) zeigt Linien, die ihn mit den Boxen jedes Subtyps verbinden.

Jeder Subtyp (a) erscheint wiederum in einem eigenen Feld und (b) enthält ausschließlich seine anwendbaren Eigenschaften. Der PRIMARY KEY des Supertyps PersonId migriert 5 zu den Subtypen mit den Rollennamen 6 ActorId , DirectorId bzw. WriterId .

Außerdem habe ich vermieden, Person mit dem UserProfile- Entitätstyp zu koppeln , wodurch alle kontextbezogenen Implikationen, Zuordnungen oder Beziehungen usw. getrennt werden können. Die PersonId- Eigenschaft wurde mit dem Rollennamen UserId nach UserProfile migriert .

Sie geben im Fragenkörper an, dass

Und alle Schauspieler müssen mindestens eine URL für eines ihrer anderen Online-Schauspielerprofile angeben. Derzeit gibt es drei, die sie einschließen können, aber diese Anzahl kann sich erhöhen.

Also ist URL ein eigenständiger Entitätstyp und wird gemäß diesem Zitat direkt mit dem Subtyp Actor verknüpft .

Und in Kommentaren geben Sie das an

[…] Ein Schauspieler hat einen Kopfschuss (Foto), ein Schriftsteller nicht […]

… Dann habe ich unter anderem Headshot als Eigenschaft des Entitätstyps Actor aufgenommen .

Die Entitätstypen " Ethnizität" und " Ort " können natürlich komplexere Organisationen beinhalten (z. B. kann ein Schauspieler in unterschiedlichen Anteilen einer, zwei oder mehr verschiedenen ethnischen Gruppen angehören, und ein Verfasser kann auf einem Ort basieren, der aufgezeichnet werden muss Land, Verwaltungsregion, Landkreis usw.), aber es sieht so aus, als würden die Anforderungen Ihres Geschäftskontexts mit den hier modellierten Strukturen erfolgreich abgedeckt.

Natürlich können Sie so viele Anpassungen wie nötig vornehmen.

Illustratives logisches SQL-DDL-Design

Infolgedessen habe ich basierend auf dem oben gezeigten und beschriebenen IDEF1X-Diagramm das folgende logische DDL-Layout geschrieben (ich habe Anmerkungen als Kommentare geliefert, die einige der Merkmale erläutern, die ich in Bezug auf die Tabellen, Spalten und Einschränkungen für besonders wichtig halte erklärt):

-- You should determine which are the most fitting 
-- data types and sizes for all your table columns 
-- depending on your business context characteristics.

-- Also, you should make accurate tests to define the 
-- most convenient INDEX strategies based on the exact 
-- data manipulation tendencies of your business needs.

-- As one would expect, you are free to utilize 
-- your preferred (or required) naming conventions. 

CREATE TABLE Person ( -- Represents the supertype.
    PersonId       INT      NOT NULL,
    FirstName      CHAR(30) NOT NULL,
    LastName       CHAR(30) NOT NULL,
    BirthDate      DATE     NOT NULL,
    GenderCode     CHAR(3)  NOT NULL,
    TwitterProfile CHAR(30) NOT NULL,
    PhoneNumber    CHAR(30) NOT NULL,
    EmailAddress   CHAR(30) NOT NULL,  
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Person_PK  PRIMARY KEY (PersonId),
    CONSTRAINT Person_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
        FirstName,
        LastName,
        GenderCode,
        BirthDate
    ),
    CONSTRAINT Person_AK2 UNIQUE (TwitterProfile), -- ALTERNATE KEY.
    CONSTRAINT Person_AK3 UNIQUE (EmailAddress)    -- ALTERNATE KEY.
);

CREATE TABLE Ethnicity ( -- Its rows will serve a “look-up” purpose.
    EthnicityId     INT      NOT NULL,
    Name            CHAR(30) NOT NULL,  
    Description     CHAR(30) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Ethnicity_PK PRIMARY KEY (EthnicityId),
    CONSTRAINT Ethnicity_AK UNIQUE      (Description)   
);

CREATE TABLE Actor ( -- Stands for one of the subtypes.
    ActorId         INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Headshot        CHAR(30) NOT NULL, -- May, e.g., contain a URL indicating the path where the photo file is actually stored. 
    EthnicityId     INT      NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Actor_PK            PRIMARY KEY (ActorId),
    CONSTRAINT ActorToPerson_PK    FOREIGN KEY (ActorId)
        REFERENCES Person (PersonId),
    CONSTRAINT ActorToEthnicity_PK FOREIGN KEY (EthnicityId)
        REFERENCES Ethnicity (EthnicityId)   
);

CREATE TABLE Director ( -- Denotes one of the subtypes
    DirectorId      INT       NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Bio             CHAR(120) NOT NULL,  
    Etcetera        CHAR(30)  NOT NULL,
    CreatedDateTime DATETIME  NOT NULL,
    -- 
    CONSTRAINT Director_PK         PRIMARY KEY (DirectorId),
    CONSTRAINT DirectorToPerson_PK FOREIGN KEY (DirectorId)
        REFERENCES Person (PersonId)   
);

CREATE TABLE Country (
    CountryCode     CHAR(2)  NOT NULL,
    Name            CHAR(30) NOT NULL,  
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Country_PK PRIMARY KEY (CountryCode),
    CONSTRAINT Country_AK UNIQUE      (Name)   
);

CREATE TABLE Location ( -- Its rows will serve a “look-up” purpose.
    CountryCode     CHAR(2)  NOT NULL,
    LocationCode    CHAR(3)  NOT NULL,
    Name            CHAR(30) NOT NULL,  
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Location_PK PRIMARY KEY (CountryCode, LocationCode),
    CONSTRAINT Location_AK UNIQUE      (CountryCode, Name)   
);

CREATE TABLE Writer ( -- Represents one of the subtypes.
    WriterId        INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    CountryCode     CHAR(2)  NOT NULL,
    LocationCode    CHAR(3)  NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Writer_PK           PRIMARY KEY (WriterId),
    CONSTRAINT WriterToPerson_PK   FOREIGN KEY (WriterId)
        REFERENCES Person (PersonId),
    CONSTRAINT WriterToLocation_PK FOREIGN KEY (CountryCode, LocationCode)
        REFERENCES Location (CountryCode, LocationCode)  
);

CREATE TABLE UserProfile (
    UserId          INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    UserName        CHAR(30) NOT NULL,
    Etcetera        CHAR(30) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT UserProfile_PK PRIMARY KEY (UserId),
    CONSTRAINT UserProfile_AK UNIQUE      (UserName), -- ALTERNATE KEY.
    CONSTRAINT UserProfileToPerson_PK FOREIGN KEY (UserId)
        REFERENCES Person (PersonId)    
);

CREATE TABLE URL (
    ActorId       INT      NOT NULL,
    Address       CHAR(90) NOT NULL,
    Etcetera      CHAR(30) NOT NULL,
    AddedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT URL_PK        PRIMARY KEY (ActorId, Address), -- Composite PRIMARY KEY.
    CONSTRAINT URLtoActor_FK FOREIGN KEY (ActorId)
        REFERENCES Actor (ActorId)
);

Daher hat (1) jeder einzelne Aspekt des obigen logischen Layouts eine sehr genaue Bedeutung aus (2) einem einzelnen Merkmal des interessierenden Geschäftsumfelds 7 - in Übereinstimmung mit dem Geist des relationalen Rahmens von Dr. Edgar Frank Codd -, da:

  • Jede Basistabelle repräsentiert einen einzelnen Entitätstyp.
  • Jede Spalte steht für eine einzelne Eigenschaft des jeweiligen Entitätstyps.
  • Für jede Spalte wird ein bestimmter Datentyp festgelegt , um sicherzustellen, dass alle darin enthaltenen Werte zu einer bestimmten und ordnungsgemäß abgegrenzten Menge a gehören, sei es INT, DATETIME, CHAR usw. (und wir hoffen, dass MySQL DOMAIN endlich enthält Unterstützung in naher Zukunft).
  • Mehrere Einschränkungen werden (deklarativ) konfiguriert, um sicherzustellen, dass die in allen Tabellen enthaltenen Zusicherungen in Form von Zeilen den auf konzeptioneller Ebene festgelegten Geschäftsregeln entsprechen.
  • Jede Zeile soll eine genau definierte Semantik vermitteln, z. B. wird eine PersonZeile gelesen

    Die Person identifiziert durch PersonId rvon der Vorname genannt wird sund der Name t, wurde am Birth geboren u, hat die GenderCode v, Tweets auf das Twitterprofil wwird durch Phone erreicht x, wird über die Emailaddress kontaktiert yund am CreatedDateTime registriertz .

Ein solches Layout ist ausgesprochen günstig, da Sie neue Tabellen ableiten können (z. B. SELECT-Operationen, die mithilfe der JOIN-Klausel Spalten aus mehreren Tabellen erfassen), die nacheinander ebenfalls eine sehr genaue Bedeutung haben (siehe Abschnitt) mit dem Titel "Ansichten" unten).

Es ist zu erwähnen, dass bei dieser Konfiguration (i) eine Zeile, die eine Subtypinstanz darstellt, durch (ii) denselben PRIMARY KEY-Wert identifiziert wird, der die Zeile unterscheidet, die das Auftreten des komplementären Supertyps bezeichnet. Daher ist es mehr als angebracht, dies zu bemerken

  • (a) Das Anhängen einer zusätzlichen Spalte für systemgenerierte und vom System zugewiesene Ersatzzeichen 8 an (b) die Tabellen, die für die Untertypen stehen, ist (c) völlig überflüssig .

Wenn bei diesem logischen Entwurf neue Untertypen in Ihrem Geschäftskontext als relevant definiert werden, müssten Sie eine neue Basistabelle deklarieren. Dies ist jedoch auch dann der Fall, wenn andere Arten von Entitätstypen als von Bedeutung erachtet werden Tatsache, gewöhnlich.

Ansichten

Um beispielsweise alle Informationen abzurufen, die einem Schauspieler , Regisseur oder Autor entsprechen , können Sie einige Ansichten (dh abgeleitete oder ausdrucksstarke Tabellen) deklarieren, sodass Sie direkt aus einer einzelnen Ressource auswählen können, ohne die schreiben zu müssen in Bezug auf JOINs jedes Mal; Mit der unten deklarierten ANSICHT können Sie beispielsweise die "vollständigen" Schauspielerinformationen erhalten :

--
CREATE VIEW FullActor AS

    SELECT P.FirstName,
           P.Lastname,
           P.BirthDate,
           P.GenderCode,
           P.TwitterProfile,
           P.PhoneNumber,
           P.EmailAddress,
           A.Headshot,
           E.Name AS Ethnicity
         FROM Person P
         JOIN Actor A
           ON A.ActorId     = P.PersonId
         JOIN Ethnicity E
           ON E.EthnicityId = A.EthnicityId;
--

Natürlich können Sie einen ähnlichen Ansatz verfolgen, um die „vollständigen“ Director- und Writer- Informationen abzurufen :

--
CREATE VIEW FullDirector AS

    SELECT P.FirstName,
           P.Lastname,
           P.BirthDate,
           P.GenderCode,
           P.TwitterProfile,
           P.PhoneNumber,
           P.EmailAddress,
           D.Bio,
           D.Etcetera
         FROM Person P
         JOIN Director D
           ON D.DirectorId = P.PersonId; 

--
CREATE VIEW FullWriter AS

    SELECT P.FirstName,
           P.Lastname,
           P.BirthDate,
           P.GenderCode,
           P.TwitterProfile,
           P.PhoneNumber,
           P.EmailAddress,
           L.Name AS Location,
           C.Name AS Country
         FROM Person P
         JOIN Writer W
           ON W.WriterId     = P.PersonId
         JOIN Country C
           ON C.CountryCode  = W.CountryCode
         JOIN Location L
           ON L.LocationCode = W.LocationCode;   
--

Ich habe alle DDL-Anweisungen und DML-Ansichten, die hier in dieser SQL-Geige unter MySQL 5.6 behandelt werden, veröffentlicht, damit Sie sie "in Aktion" sehen und testen können.


Endnoten

1 In einigen konzeptionellen Modellierungstechniken werden Supertyp-Subtyp-Assoziationen als Superklasse-Subklasse- Beziehungen bezeichnet.

2 Sie erwähnen zwar, dass es tatsächlich mehr Rollen gibt , die eine Person ausführen kann, aber die drei, die Sie enthüllt haben, sind gut genug, um das Szenario zu diskutieren, das mehrere wichtige Konsequenzen aufdeckt .

3 Wie Sie bereits bemerkt haben, kann ein Akteur in Zukunft möglicherweise eine bis viele URLs bereitstellen .

4 Integration Definition für Information Modeling ( IDEF1X ) ist eine sehr empfehlenswert Modellierungstechnik, die als etabliert wurde Standard im Dezember 1993 von dem Vereinigten Staaten National Institute of Standards and Technology (NIST). Es basiert auf (a) den frühen theoretischen Arbeiten, die vom alleinigen Urheber des relationalen Datenmodells verfasst wurden, dh Dr. EF Codd; zu (b) der von Dr. PP Chen entwickelten Entity-Relationship-Sicht ; und auch auf (c) der Logical Database Design Technique, erstellt von Robert G. Brown.

5 Der IDEF1X-Standard definiert die Schlüsselmigration als „Modellierungsprozess zum Platzieren des Primärschlüssels einer übergeordneten oder generischen Entität [dh eines Supertyps] in ihrer untergeordneten oder Kategorieentität [dh eines Subtyps] als Fremdschlüssel“.

6 In IDEF1X ein Rollenname ist eine unterscheidende Markierung an ein FK - Attribut zugeordnet, um die Bedeutung auszudrücken , dass es im Rahmen seiner jeweiligen Entitätstyp hält.

7 Mit Ausnahme der hypothetischen konzeptionellen Eigenschaften (und logischen Spalten) Director.Etcetera und UserProfile.Etcetera , die lediglich Platzhalter sind, mit denen ich die Möglichkeit des Hinzufügens weiterer Eigenschaften (und Spalten) für den entsprechenden konzeptuellen Entitätstyp offengelegt habe (und logische Tabelle).

8 Hängen Sie beispielsweise eine zusätzliche Spalte mit dem Attribut AUTO_INCREMENT an eine Tabelle einer Datenbank an, die unter MySQL ausgeführt wird.

MDCCL
quelle
2

Sie sollten dies auf folgende Tabellen aufteilen (nur die Spalten anzeigen, die zur Darstellung des Konzepts erforderlich sind, nicht unbedingt alle Spalten):

Users
ID   Username   FirstName   LastName   PasswordHash ...
 1   'Joe1'      'Joe'      'Smith'
 2   'Freddy'    'Fred'     'Jones'

Roles
ID   RoleType ....
 1   'Writer'
 2   'Director'
 3   'Actor'

User_Roles
User_ID   Role_ID ...
1         1
1         2
2         2
2         3

Auf diese Weise erhalten Sie eine Tabelle voller Benutzer mit allen verschiedenen Benutzerspalten, eine Rollentabelle und eine Verknüpfungstabelle, um die beiden miteinander zu verbinden.

An den Einträgen in User_Roles können Sie erkennen, dass Joe1 sowohl Autor als auch Regisseur ist. Und Freddy ist sowohl Regisseur als auch Schauspieler.

Auf diese Weise können Sie später weitere Rollen hinzufügen, ohne das System zu ändern. Fügen Sie einfach Datensätze für Producer oder Editor oder was auch immer ein.

Um alle Benutzernamen von Schauspielern zu finden, haben Sie mehrere Möglichkeiten:

 Select Distinct Username
   from Users
  Where User_ID in (select User_ID from User_Roles where Role_ID = 3)

Oder wenn Sie die Rolle_ID-Nummer nicht kennen, dann:

 Select Distinct Username
   from Users
  Where User_ID in (Select User_ID from User_Roles where Role_ID = 
                       (Select ID from Roles where RoleType = 'Actor')
                   )

Oder Sie können dies auch tun:

select u.Username, r.RoleType
  from Users u
 inner join User_Roles ur on ur.User_ID = u.ID
 inner join Roles r on r.ID = ur.Role_ID
 where r.RoleType = 'Actor'

(In dieser Version können Sie auch verwenden Where r.Role_ID = 3, um die gleichen Ergebnisse zu erzielen.)

Aber ich würde die erste Abfrage und die WHERE-Klausel verwenden, die ich kannte. In einem großen System läuft die Kenntnis der Role_ID im Allgemeinen schneller als der Text, da numerische Daten für die meisten SQL-Engines "einfacher" und effizienter sind, um die Indizes zu verarbeiten.

Kontaktmethoden oder Bilder oder was auch immer, ich würde sie auf ähnliche Weise tun:

Attributes
ID    MethodText    ...
1     'TwitterID'
2     'URL'
3     'CellPhone'
4     'Email'
5     'PictureLink'

Role_Attributes
Role_ID  Attribute_ID isRequired
3        5             1
3        4             1
3        3             0

User_Attributes
User_ID  Attribute_ID  AttributeData
1         4            '[email protected]'
1         1            '@joe'
1         3            '555-555-5555'
1         5            'www.example.com/pics/myFace.png'

...und so weiter. Diese würden auf die gleiche Weise wie die Benutzer mit Rollen verknüpft.

Dies zeigt, dass jede Rolle 0 bis viele Attribute hat, die optional sein können. Dann hat jeder Benutzer 0 bis viele Attribute mit den Daten für diese Attribute.

Auf diese Weise können Sie im Laufe der Zeit neue Attribute hinzufügen, ohne Code neu schreiben zu müssen. Aktualisieren Sie einfach die Tabelleneattribute und role_attributes, um sie Ihren neuen Regeln anzupassen. Außerdem können Sie Attribute zwischen Rollen austauschen, ohne für jeden Benutzer dieselben Daten erneut eingeben zu müssen. Wenn für zwei Rollen Bilder erforderlich sind, müssen sie nur 1 Bild hochladen, um diese Anforderung zu erfüllen.

Nocken
quelle
Aha, ich denke, das macht in einer Hinsicht Sinn ... aber ich bin mir nicht so sicher, wie ich zum Beispiel alle Schauspieler zusammen mit beispielsweise ihren Benutzernamen auflisten würde (vorausgesetzt, die Schauspieler-y-Daten sind in gespeichert eine separate Tabelle).
Verism
Siehe meine Änderungen; Ich habe Abfragebeispiele hinzugefügt.
CaM
Das ist sehr hilfreich, danke. Ich glaube, ich war in meiner Frage nicht ganz klar - sorry. Ich hätte klarer machen sollen, dass die Tabellen für jeden Typ (Schauspieler, Regisseur usw.) ihre eigenen eindeutigen Attribute haben, die nur für diesen Benutzertyp relevant sind. Zum Beispiel hat ein Schauspieler einen Kopfschuss (Foto), ein Schriftsteller nicht. Nochmals eine Entschuldigung dafür, dass dies nicht expliziter ist.
Verism
Die Kontaktmethoden scheinen eine großartige Lösung zu sein.
Verism
1
Das wurde in Attribute geändert, um die Anforderungen für Fotos usw. zu erfüllen. Sollte jetzt besser passen.
CaM