35 votes

Les clés et les valeurs générées par le serveur ne sont pas prises en charge par SQL Server Compact.

Je viens de commencer à jouer avec le cadre des entités, et j'ai décidé de le connecter à ma base de données SQL Server CE existante. J'ai une table avec une clé primaire IDENTITY(1, 1) mais quand j'ai essayé d'ajouter une entité, j'ai eu l'erreur mentionnée ci-dessus.

De Article de MS Technet J'ai appris que

SQL Server Compact ne prend pas en charge les entités dont les clés ou les valeurs sont générées par le serveur lorsqu'il est utilisé avec Entity Framework. Lors de l'utilisation de l'Entity Framework, les clés d'une entité peuvent être marquées comme générées par le serveur. Cela permet à la base de données de générer une valeur pour la clé lors de l'insertion ou de la création de l'entité. En outre, zéro ou plusieurs propriétés d'une entité peuvent être marquées comme des valeurs générées par le serveur. Pour plus d'informations, voir la rubrique Store Generated Pattern dans la documentation d'Entity Framework. SQL Server Compact ne prend pas en charge les entités avec des clés ou des valeurs générées par le serveur lorsqu'il est utilisé avec l'Entity Framework, bien que l'Entity Framework vous permette de définir des types d'entités avec des clés ou des valeurs générées par le serveur. Une opération de manipulation de données sur une entité ayant des valeurs générées par le serveur déclenche une exception "Not supported".

Alors maintenant, j'ai quelques questions :

  • Pourquoi marquer la clé comme générée par le serveur si elle n'est pas prise en charge et qu'elle lève une exception ? Il est difficile de comprendre le paragraphe cité.
  • Lorsque j'ai essayé d'ajouter StoreGeneratedPattern="Identity" à la propriété de mon entité, Studio m'a signalé que cette option n'était pas autorisée. Qu'est-ce que je fais de mal ?
  • Quelle est la meilleure solution pour pallier à cette limitation (y compris le passage à une autre base de données) ? Mes limites sont l'installation zéro et l'utilisation de l'entity framework.

24voto

mostlytech Points 641

Lorsque j'ai rencontré cette limitation, j'ai changé le type en identifiant unique.

17voto

La meilleure solution consiste à utiliser un identifiant unique ou à générer manuellement une valeur de clé bigint/int.

Quelque chose comme ça peut-être ...

    private static object lockObject = new object();

    private static long nextID = -1;

    public static long GetNextID()
    {
        lock (lockObject)
        {
            if (nextID == -1) nextID = DateTime.UtcNow.Ticks; else nextID++;
            return nextID;
        }
    }

Cela suppose que vous ne génériez pas plus d'un enregistrement par tic pendant l'exécution d'une application (plus le temps d'arrêt et de redémarrage). C'est une hypothèse raisonnable, je crois, mais si vous voulez une solution totalement infaillible (mais plus complexe), lisez l'ID le plus élevé dans la base de données et incrémentez à partir de là.

6voto

Pablonete Points 552

SQL CE version 4.0 a corrigé ce problème avec son fournisseur Entity Framework.

4voto

Thomas Levesque Points 141081

Je viens de rencontrer ce problème également... La réponse de Mosttech est probablement la meilleure option, les GUIDs sont très faciles à utiliser et le risque de collision des clés est très faible (mais pas inexistant).

  • Pourquoi marquer la clé comme générée par le serveur si elle n'est pas prise en charge et qu'elle lève une exception ? Il est difficile de comprendre le paragraphe cité.

Parce que SQL Server (pas Compact) le supporte, et que d'autres tiers peuvent le supporter aussi... Entity Framework n'est pas seulement pour SQL Server Compact ;)

4voto

Mike Christiansen Points 561

Dans mon cas, toutes mes classes ont la clé primaire nommée "ID".

J'ai créé une interface

public class IID
{
    public Int32 ID { get; set; }
}

Ensuite, je crée une méthode d'extension

public static Int32 GetNextID<T>(this ObjectSet<T> objects)
    where T : class, IID
    {
        T entry = objects.OrderByDescending(u => u.ID).FirstOrDefault();
        if (entry == default(T))
            return 1;
        return entry.ID + 1;
    }

Ensuite, quand j'ai besoin d'une nouvelle identité, je fais ça :

MyObject myobj = new MyObject();
myobj.ID = entities.MyTable.GetNextID();

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