Question

Je suis nouveau dans Entity Framework et j'ai problème avec quelque chose qui était assez facile en t-sql pur. Supposons que nous ayons table avec 3 colonnes. Id (identité, clé primaire), IdKind (int), numéro (int). La colonne nubmer dépend de la colonne IdKind. Les données dans ce tableau devrait ressembler à ceci:

Id | IdKind | Nombre

1 | 1 | 1

2 | 1 | 2

3 | 1 | 3

4 | 2 | 1

5 | 2 | 2

6 | 2 | 3

Comme vous pouvez le voir le numéro de colonne est auto incrémentée dépend de IdKind. Dans t-sql, je découvrais max (nombre) + 1 pour un certain IdKind. Tout était dans une procédure stockée dans une transaction si la valeur du nombre est unique pour IdKind.

Comment accomplir la même chose dans Entity Framework. Valeur du numéro devrait être calculé lors de la création de nouveaux objets ou lors d'un changement IdKind.

Était-ce utile?

La solution

J'utiliser la base de données pour déclencheur et qui configure propriété Number dans la cartographie EF avec EF StoreGeneratedPattern.Computed pour informer que cette propriété est rempli dans la base de données et doit être rechargée après chaque mise à jour / insertion.

J'utiliserais pas non plus max () pour chaque nouveau numéro. Au lieu de cela, je maintiendrais table séparée simulant des séquences. Ce tableau doit contenir enregistrement par séquence - dans votre dossier de cas par IdKind avec le numéro courant max. Au lieu de sélectionner l'agrégation vous sélectionnerez seul enregistrement et le mettre à jour pour contenir le nouveau numéro max. Travailler avec ce tableau doit être dans la même transaction que la persistance des changements à votre entité.

Autres conseils

J'ai eu le même problème, mais je l'ai résolu en c #.

devrait avoir une entité mappée sur la table:

public class MyEntity
{ 
     Kind IdKind{get; set;}
     int Number{get;set;}
}

Je devrais avoir et entité auxiliaire pour stocker le dernier numéro utilisé par Kind.

public class LastNumber
{ 
     Kind IdKind{get;set;}
     int LastNumber{get;set;}
}

Ensuite, avant d'ajouter une ligne (objet MyEntity) à la table, je calculer le bon numéro en utilisant le champ LastNumber du LastNumberEntity Sincères égale à ma valeur Kind.

Il faut noter que cette stratégie a un problème de concurrence, car deux threads différents pourraient être un objet de l'ajout du même genre en même temps, ces discussions vont inspecter la même LastNumberEntity pour obtenir la valeur LastNumber. Ce problème a une solution connue dans entityframework. Le code pourrait ressembler à ceci:

 public int GetNumber(Kind idKind)
    {
        using (var db = new MyDataContext())
        {
            var lastNumber = db.LastNumbers.Single(x=>x.IdKind == idKind);
            for (int attemps = 0; attemps < 10;)
            {
                try
                {
                    lastNumber.LastNumber++;
                    db.SaveChanges();
                    return lastNumber.LastNumber;
                }
                catch (DbUpdateConcurrencyException ex)
                {
                    attemps++;
                }
            }
        }

        throw new Exception("Many concurrency calls");
    }

Cette méthode est un nombre supplémentaire pour un type spécifié et gère le problème de la concurrence, en l'utilisant, nous pouvons définir la valeur numérique pour chaque objet MyEntity. Le code client pourrait ressembler à ceci:

var entity = new MyEntity();
var number = GetNumber(entity.IdKind);
entity.Number = number;
db.MyEntities.Add(entity);
db.SaveChanges();

Ce code pourrait être refactorisé, ce qui rend les setters privés, ce qui rend une usine pour assurer les entités sont toujours créées à l'aide de la méthode GetNumber et l'utilisation de référentiels pour gérer le db.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top