Une propriété dépendante dans une ReferentialConstraint est mappée à une colonne générée par le magasin

98

J'obtiens cette erreur lors de l'écriture dans la base de données:

Une propriété dépendante dans un ReferentialConstraint est mappée à une colonne générée par le magasin. Colonne: 'PaymentId'.

public bool PayForItem(int terminalId, double paymentAmount, 
      eNums.MasterCategoryEnum  mastercategoryEnum, int CategoryId, int CategoryItemId)
    {

        using (var dbEntities = new DatabaseAccess.Schema.EntityModel())
        {
            int pinnumber = 0;
            long pinid = 1; //getPinId(terminalId,ref pinnumber) ;
            var payment = new DatabaseAccess.Schema.Payment();
            payment.CategoryId = CategoryId;
            payment.ItemCategoryId = CategoryItemId;
            payment.PaymentAmount = (decimal)paymentAmount;
            payment.TerminalId = terminalId;
            payment.PinId = pinid;

            payment.HSBCResponseCode = "";
            payment.DateActivated = DateTime.Now;
            payment.PaymentString = "Payment";
            payment.PromotionalOfferId = 1;
            payment.PaymentStatusId = (int)eNums.PaymentStatus.Paid;

            //payment.PaymentId = 1;

            dbEntities.AddToPayments(payment);
            dbEntities.SaveChanges();
        }
        return true;
    }

Le schéma est:

entrez la description de l'image ici

Roi gallois
la source

Réponses:

180

Est-il possible que vous ayez défini une mauvaise relation de colonne entre vos tables? colonnes différentes et une a été définie comme autonumérique.

Cela m'est arrivé.

ju4nj3
la source
55
J'ai par erreur fait d'une de mes clés étrangères une identité (incrémentation automatique). C'est l'erreur que j'ai.
jocull le
3
Doh! J'avais laissé la partie clé étrangère de la relation comme valeur par défaut donnée par SQL Server 2008 Management Studio, qui était les champs de clé primaire de la table enfant, et non la colonne que j'avais créée pour contenir la valeur de clé étrangère.
robaker
12
Si vous inspectez l'exception dans la fenêtre Quick Watch (c'est-à-dire (e as System.Data.Entity.Infrastructure.DbUpdateException).Entries), vous pouvez voir quelle table contient la clé primaire référencée.
Cᴏʀʏ
17
Ne serait-il pas cool que les messages d'erreur EF indiquent simplement quel était le problème au lieu de cracher gobbledy-gook?
AR
J'ai utilisé cette requête pour afficher toutes les relations dans une seule vue stackoverflow.com/questions/8094156/...
Dave
47

Cette erreur indique que vous utilisez une relation non prise en charge ou que vous avez une erreur dans votre mappage. Votre code n'a probablement aucun rapport avec l'erreur.

L'erreur signifie que vous avez une relation entre les entités où la propriété de clé étrangère dans l'entité dépendante est définie comme étant générée par le magasin. Les propriétés générées par le magasin sont renseignées dans la base de données. EF ne prend pas en charge les propriétés générées par le magasin en tant que clés étrangères (ainsi que les propriétés calculées dans les clés primaires).

Ladislav Mrnka
la source
2
je peux ajouter la ligne dans le serveur SQL avec les mêmes informations. quand vous dites Store Generated, pouvez-vous donner un exemple?
Welsh King
1
EF n'est pas SQL Server. Il a sa propre limitation. Trouvez simplement où vous utilisez une propriété FK générée par DB PaymentIDet traitez-la.
Ladislav Mrnka
ok nous avons une table d'historique de paiement qui a paymentId comme clé étrangère, dois-je ajouter une ligne là-dedans?
Welsh King
Il ne s'agit pas d'ajouter une ligne mais de définir la colonne. Comment définissez-vous cette colonne?
Ladislav Mrnka
il suffit de cliquer sur le modèle de relation dans Visual Studio et je reçois le nom «Paiement» ne peut pas être utilisé dans le type «Paiement». les noms de membres ne peuvent pas être identiques à leur type englobant. Toutes les idées
Welsh King
8

J'ai eu le même problème. Sur la base des réponses fournies ici, j'ai pu le suivre et le résoudre, mais j'avais un problème étrange décrit ci-dessous - cela pourrait aider quelqu'un à l'avenir.

Sur mes tables dépendantes, les colonnes de clé étrangère ont été définies sur StoreGeneratedPattern = "Identity". J'ai dû le changer en "Aucun". Malheureusement, cela n'a pas fonctionné du tout.

J'ai regardé dans le XML généré par le concepteur (SSDL) et ces propriétés étaient toujours là, je les ai donc supprimées manuellement. J'ai également dû réparer les colonnes de la base de données (supprimer l'identité (1,1) de CREATE TABLE SQL)

Après cela, le problème a disparu.

surfen
la source
Merci pour cette astuce. Changer le champ dans le concepteur de Identité à Aucun a changé cela à un endroit dans l'EDMX, mais pas à l'autre endroit, donc j'ai toujours l'erreur jusqu'à ce que je modifie moi-même le fichier EDMX. Malheureusement, EntityFramework est ensuite devenu fou et a essayé de réinsérer des entités liées dans d'autres tables, mais c'était quand même une aide pour contourner ce message d'erreur.
FTWinston
6

J'ai eu le même problème et après avoir creusé dans la conception de la table dans le serveur SQL, j'ai trouvé que par erreur, j'avais défini la clé primaire de la table également comme clé étrangère.

flux de conception de table de serveur SQL

Dans cette image, vous pouvez voir que JobID est la clé primaire de la table mais aussi par erreur la clé étrangère.

Manish Bhakuni
la source
2

Mon problème était dû à la définition redondante de la clé primaire dans la configuration.

this
   .Property(p => p.Id)
   .HasColumnName(@"id")
   .IsRequired()
   .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity) // this is redundant when you want to configure a One-to-Zero-or-One relationship
   .HasColumnType("int");

Supprimer cette ligne

.HasDatabaseGeneratedOption (DatabaseGeneratedOption.Identity)


Exemple http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx

Cela suffit pour définir la relation

// Configure Student & StudentAddress entity
modelBuilder.Entity<Student>()
            .HasOptional(s => s.Address) // Mark Address property optional in Student entity
            .WithRequired(ad => ad.Student); // mark Student property as required in StudentAddress entity. Cannot save StudentAddress without Student
Piotr
la source
1

Revérifiez la relation entre Paiement et les autres tables / entités. Y compris ceux qui ne devraient pas contenir PaymentId, car c'est là que le problème se cache probablement.

Lors de la création de clés étrangères dans SQL Server Management Studio, la clé primaire est définie par défaut et cette valeur par défaut est rétablie lorsque la table parent est modifiée, veillez donc à modifier les valeurs dans le bon ordre dans la fenêtre «Tables et colonnes».

De plus, une fois que vous avez corrigé la relation problématique, il y a de fortes chances qu'une simple "actualisation" du modèle ne supprime pas correctement la relation erronée du modèle et vous obtiendrez la même erreur même après le " correctif ", alors faites-le vous-même dans le modèle avant d'effectuer une actualisation. (J'ai découvert cela à la dure.)

marque
la source
1

Si vous avez vérifié vos relations et que vous y êtes bien.

Supprimez la table dans edmx, puis mettez à jour à partir de la base de données. Cela vous évitera de faire la mise à jour manuellement.

rickjr82
la source
Vraiment merci pour vos conseils, j'ai passé 1 heure à valider ma base de données, mais après suppression puis mise à jour, tout va bien.
Tấn Nguyên
1

Pour moi, c'était une clé étrangère mal placée dans la table, mais même après avoir modifié la table pour la corriger, cela ne fonctionnait toujours pas. Vous devez mettre à jour les fichiers EDMX (et pas assez pour "rafraîchir" la table du modèle, vous devez supprimer et ajouter à nouveau la table dans le modèle).

knocte
la source
1

En plus de la réponse acceptée, si vous utilisez le générateur EF Reverse POCO ou un autre outil qui génère vos POCO, assurez-vous de les régénérer !

adam0101
la source
N'oubliez jamais de réexécuter votre outil T4 personnalisé (contenant les POCO) après avoir modifié votre générateur de modèle EF DB-first externe (contenant les contextes) ... JAMAIS! XD (aurait tout aussi bien pu devenir fou -.- ')
Shockwaver
0

Dans mon cas, le problème a été causé par une relation bidirectionnelle 1-1:

class Foo{
[Key]
Id
[ForeignKey]
BarId
...
}
class Bar{
[Key]
Id
[ForeignKey]
FooId
...
}

J'ai simplement dû supprimer l'une des deux clés étrangères (pas nécessaire de toute façon).

wecky
la source
0

Dans mon cas, c'était simplement que je n'avais pas les autorisations correctement définies sur la base de données. J'avais mis en lecture seule et le framework Entity me donnait une erreur ReferentialConstraint qui m'a rejeté. Ajout d'autorisations d'écriture supplémentaires et tout allait bien.

Mdhattr
la source
0

Dans mon cas, j'avais une propriété générée par la base de données et une propriété de navigation ForeignKey configurée pour référencer une table associée 1 à 1.

Ce n'était pas quelque chose que je pouvais supprimer, je devais pouvoir à la fois définir la clé primaire de l'entité pour qu'elle soit générée par la base de données ET je devais pouvoir référencer la table 1 à 1 en tant que propriété de navigation.

Je ne sais pas si c'est la même chose pour les autres, mais ce problème n'apparaissait que lors de la création d'une nouvelle entité, la lecture ou la modification d'entités existantes ne présentait pas le problème, j'ai donc contourné le problème en créant une version héritée de mon contexte et en utilisant la méthode Fluent pour désactiver la propriété de navigation lors de la création.

Donc, mon entité d'origine ressemblait à ceci:

public partial class MyEntity
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid id{ get; set; }


    // Navigation
    [ForeignKey("id")]
    public PathEntity Path { get; set; }
}

J'ai donc créé un contexte hérité spécial qui ressemblait à ceci:

    private class _navPropInhibitingContext : EF.ApplicationDBContext
    {
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<MyEntity>()
                .Ignore(e => e.Path);

        }
    }

puis changé le code qui a créé la nouvelle entité pour rendre l'utilisateur du nouveau type de contexte

    using (var specialContext = new _navPropInhibitingContext())
    {
        var dbModel = new MyEntity() 
        {
            ...
        };

        specialContext.MyEntity.Add(dbModel);
        await specialContext.SaveChangesAsync();
    }

J'espère que cela aide quelqu'un

Chris Terry
la source
0

Dans mon cas, le champ Id qui FK uniquement dans Entity Framework, la propriété "StoreGeneratedPattern" a été définie sur "Itentity" au lieu de "None"

Lev K.
la source