99 votes

Comment déclarer des relations de clé étrangère à l'aide de Code First Entity Framework (4.1) dans MVC3?

J'ai été à la recherche de ressources sur la façon de déclarer les relations de clé étrangère et d'autres contraintes en utilisant le premier code EF 4.1 sans beaucoup de chance. Fondamentalement, je suis la construction du modèle de données dans le code et à l'aide de MVC3 à la requête de ce modèle. Tout fonctionne via MVC qui est génial (bravo à Microsoft!) mais maintenant, je le veux de ne PAS travailler parce que j'ai besoin d'avoir des données modèle de contraintes.

Par exemple, j'ai un objet de Commande qui a une tonne de propriétés qui sont à l'extérieur des objets (tables). Droit maintenant, je peux créer une Commande, pas de problème, mais sans être en mesure d'ajouter la clé étrangère ou des objets externes. MVC3 définit cette place pas de problème.

Je me rends compte que je pourrais juste ajouter les objets moi-même dans la classe du contrôleur avant de l'enregistrer, mais je voudrais l'appel à DbContext.SaveChanges() échoue si la contrainte relations n'ont pas été respectées.

DE NOUVELLES INFORMATIONS

Donc, plus précisément, je voudrais un exception à se produire lorsque je tente de l' enregistrer une Commande sans objet la spécification d'un objet client. Cette ne semble pas être le problème si je rédigez simplement les objets comme décrit dans la plupart des le Premier Code EF de la documentation.

Dernier code:

public class Order
{
    public int Id { get; set; }

    [ForeignKey( "Parent" )]
    public Patient Patient { get; set; }

    [ForeignKey("CertificationPeriod")]
    public CertificationPeriod CertificationPeriod { get; set; }

    [ForeignKey("Agency")]
    public Agency Agency { get; set; }

    [ForeignKey("Diagnosis")]
    public Diagnosis PrimaryDiagnosis { get; set; }

    [ForeignKey("OrderApprovalStatus")]
    public OrderApprovalStatus ApprovalStatus { get; set; }

    [ForeignKey("User")]
    public User User { get; set; }

    [ForeignKey("User")]
    public User Submitter { get; set; }

    public DateTime ApprovalDate { get; set; }
    public DateTime SubmittedDate { get; set; }
    public Boolean IsDeprecated { get; set; }
}

C'est l'erreur que je reçois aujourd'hui lors de l'accès au VS généré vue pour le Patient:

MESSAGE D'ERREUR

Le ForeignKeyAttribute sur la propriété 'Patient' type 'PhysicianPortal.Modèles."L'ordre n'est pas valides. Le nom de clé étrangère "Parent" n'a pas été trouvé sur le type de charge 'PhysicianPortal.Modèles.La commande'. L' Nom de la valeur doivent être séparés par des virgules liste de clé étrangère noms de propriété.

En ce qui concerne,

Guido

156voto

Sergi Papaseit Points 8979

Si vous avez un Order classe, l'ajout d'une propriété qui fait référence à une autre classe dans votre modèle, par exemple Customer devrait être assez pour que les EF sais qu'il y a un lien là:

public class Order
{
    public int ID { get; set; }

    // Some other properties

    // Foreign key to customer
    public virtual Customer Customer { get; set; }
}

Vous pouvez toujours définir l' FK relation explicite:

public class Order
{
    public int ID { get; set; }

    // Some other properties

    // Foreign key to customer
    [ForeignKey("Customer")]
    public string CustomerID { get; set; }
    public virtual Customer Customer { get; set; }
}

L' ForeignKeyAttribute constructeur prend une chaîne de caractères comme paramètre: si vous le placez sur une propriété de clé étrangère, il représente le nom de la propriété de navigation. Si vous le placez sur la propriété de navigation, il représente le nom de la clé étrangère.

Ce que cela signifie est que, si vous l'endroit où placer l' ForeignKeyAttribute sur le Customer de la propriété, l'attribut prendrait CustomerID dans le constructeur:

public string CustomerID { get; set; }
[ForeignKey("CustomerID")]
public virtual Customer Customer { get; set; }

EDIT basé sur la Dernière version du Code Vous obtenez cette erreur, en raison de cette ligne:

[ForeignKey("Parent")]
public Patient Patient { get; set; }

EF recherchez une propriété appelée Parent à l'utiliser comme Clé Étrangère enforcer. Vous pouvez faire 2 choses:

1) Supprimer l' ForeignKeyAttribute et de le remplacer avec de l' RequiredAttribute pour marquer la relation:

[Required]
public virtual Patient Patient { get; set; }

La décoration d'une propriété avec l' RequiredAttribute a également un effet secondaire de nice: La relation dans la base de données est créé avec ON DELETE CASCADE.

Je recommande également de faire le bien virtual afin de permettre le Chargement Paresseux.

2) Créez une propriété nommée Parent qui va servir de Clé Étrangère. Dans ce cas, il a probablement fait plus de sens de l'appeler par exemple ParentID (vous aurez besoin de changer le nom dans l' ForeignKeyAttribute ):

public int ParentID { get; set; }

Dans mon expérience, dans ce cas, si elle fonctionne mieux dans l'autre sens:

[ForeignKey("Patient")]
public int ParentID { get; set; }

public virtual Patient Patient { get; set; }

29voto

Ladislav Mrnka Points 218632

Vous pouvez définir la clé étrangère par:

public class Parent
{
   public int Id { get; set; }
   public virtual ICollection<Child> Childs { get; set; }
}

public class Child
{
   public int Id { get; set; }
   // This will be recognized as FK by NavigationPropertyNameForeignKeyDiscoveryConvention
   public int ParentId { get; set; } 
   public virtual Parent Parent { get; set; }
}

Maintenant ParentId est propriété de clé étrangère et définit la nécessaire relation entre l'enfant et les parents. Économiser de l'enfant sans exsiting parent lèvera une exception.

Si votre FK nom de la propriété de ne pas se compose de la navigation nom de la propriété et de la mère PK nom, vous devez soit utiliser ForeignKeyAttribute annotation de données ou API fluent à la carte de la relation

Annotation de données:

// The name of related navigation property
[ForeignKey("Parent")]
public int ParentId { get; set; }

API Fluent:

modelBuilder.Entity<Child>()
            .HasRequired(c => c.Parent)
            .WithMany(p => p.Childs)
            .HasForeignKey(c => c.ParentId);

D'autres types de contraintes peuvent être appliquées par les annotations de données et la validation du modèle.

Edit:

Vous aurez une exception si vous ne définissez pas d' ParentId. Il est nécessaire de propriété (non nullable). Si vous ne le faites pas, il sera très probablement essayer d'envoyer la valeur par défaut de la base de données. La valeur par défaut est 0, donc si vous n'avez pas de client avec un Id = 0, vous obtiendrez une exception.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X