webentwicklung-frage-antwort-db.com.de

Entity Framework wird automatisch generiert GUID

Ich bin neu bei EF, also hier. Ich habe eine Klasse, die Folgendes enthält

public class EmailTemplate
{
    public Guid Id { get; set; }

    [MaxLength(2000)]
    public string Html { get; set; }
}

Hier ist meine Mapping-Klasse

class EmailMapper : EntityTypeConfiguration<EmailTemplate>
    {
        public EmailMapper()
        {
            ToTable("EmailTemplate");

            HasKey(c => c.Id);
            Property(c => c.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            Property(c => c.Id).IsRequired();
        }
    }

Ich versuche, DbContext.SaveChanges() aufzurufen, erhalte jedoch die folgende Fehlermeldung:

Ausnahmedetails: System.Data.SqlClient.SqlException: Der Wert NULL kann nicht in die Spalte 'Id' eingefügt werden. Tabelle 'AutoSendConnection.dbo.EmailTemplates'; Spalte erlaubt keine Nullen. INSERT schlägt fehl.

Was mache ich falsch? Warum erstellt EF nicht automatisch eine eindeutige GUID?

22
user2859298

Dekorieren Sie einfach das Id-Feld in Ihrer EmailTemplate-Klasse wie folgt, und SQL Server generiert automatisch den Wert beim Einfügen.

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public Guid Id { get; set; }

Sie können Ihre Mapper-Klasse auch entfernen, da sie nicht mehr benötigt wird.

41
Mark

Verwenden Sie fließende API

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Node>().Property(x => x.ID).HasDefaultValueSql("NEWID()");
}
12
Mohsen Tabareh

Setzen Sie den standardmäßigen SQL-Wert des Felds in der Mapping-Konfiguration auf 'newsequentialid ()'. 

3
Liviu M.

Andere Antworten hier ansprechen

Keine dieser anderen Optionen scheint zu funktionieren und ich habe diesmal und immer wieder mit dem EF-Team über Github nachgefragt ...

https://github.com/aspnet/EntityFramework6/issues/762

... aus irgendeinem Grund scheint das EF-Entwicklerteam zu glauben, dass dies "work by design" ist, und schließt wiederholt Tickets, um diesen "Bug" in Frage zu stellen.

Die Erklärung des EF-Teams

Aus irgendeinem Grund scheinen sie der Meinung zu sein, dass "das Generieren von Guids in SQL nicht als bewährte Methode angesehen wird und dass wir die Schlüssel im App-Code generieren sollten, um sicherzustellen, dass sie sofort verfügbar sind".

Das Problem hierbei ist natürlich, dass bei Tabellen mit hohem Datenaufkommen das Risiko besteht, dass Sie weitere Geschäftsaktionen ausführen, die einen ungültigen Schlüssel verbrauchen.

In meinem Fall könnte dies einige extrem komplexe Multi-Server-DTC-Transaktionen beschädigen, so dass ich den Rat von MS nicht für richtig halte.

Meine Antwort (die tatsächlich funktioniert)

Kurz gesagt, ich habe dieses Problem gelöst, indem ich die generierte Migration nach dem Generieren manuell gehackt habe ...

EF Code First Migrations, DB generierte Guid Keys

Um die andere Frage zu zitieren, lautet die Antwort ...

Generieren Sie das Migrationsskript wie gewohnt, indem Sie beide Attribute wie folgt auf die Schlüsseleigenschaft setzen ...

public class Foo
{
     [Key]
     [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
     public Guid Id { get; set; }
}

.. deklarativ ist die Entität nun korrekt.

Die Migration, die generiert wird, sieht ungefähr so ​​aus:

CreateTable(
    "dbo.Foos",
    c => new
        {
            Id = c.Guid(nullable: false),
            ...
        })
    .PrimaryKey(t => t.Id)
    ...;

... Ich konnte den Grund nicht genau bestimmen, aber in einigen Situationen funktioniert dies und in anderen nicht (führen Sie die Migration durch, führen Sie eine Einfügung zum Testen durch).

Wenn dies fehlschlägt, setzen Sie die Migration zurück und ändern Sie sie so, dass sie etwa wie folgt lautet:.

CreateTable(
    "dbo.Foos",
    c => new
        {
            Id = c.Guid(nullable: false, defaultValueSql: "newid()"),
            ...
        })
    .PrimaryKey(t => t.Id)
    ...;

... der zusätzliche Code hier weist SQL an, den Schlüssel wie erwartet zu generieren.

Als Faustregel würde ich diese Änderung aus Konsistenzgründen die ganze Zeit anwenden, und dies bedeutet, dass Ihre Migrationen auf einen Blick genau zeigen, welche Schlüssel db generiert werden.

2
War

Sie können den Standardwert der ID auch als NewID () in Sql Server selbst festlegen und GUID als null übergeben

Ich habe es in SSMS gemacht.

2
Moons

Ich ziehe vor, die Datenbank zu verlassen, um die ID automatisch zu generieren, zum Beispiel das folgende Schema:

CREATE TABLE [dbo].[MyTable](
    [MyId] [uniqueidentifier] NOT NULL CONSTRAINT [DF_Booking_BookingId]  DEFAULT (newsequentialid())
    )

In dem Code-First-Mapping geben Sie Folgendes an, um Entity Framework mitzuteilen, dass die Datenbank den Wert beim Einfügen erstellen soll.

Property(a => a.MyId).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
0
John