Come impostare NewId() per la GUID in entity framework

Sto creando asp.net mvc4 campione.In questo ho creato l’Id di colonna GUID nella tabella di Esempio di datacontext.

public class Sample
{
    [Required]
    public Guid ID { get; set; }
    [Required]
    public string FirstName { get; set; }
}

Questa è la tabella di entità

CreateTable(
"dbo.Samples",
 c => new
 {
     ID = c.Guid(nullable: false),
     FirstName = c.String(nullable: false)                   
 })
 .PrimaryKey(t => t.ID);

Id pass 00000000-0000-0000-0000-000000000000.

Come impostare newid() per GUID e dove devo impostare.

  • Sei sicuro di voler utilizzare un GUID come chiave primaria, si ottengono i maggiori problemi di prestazioni a causa della frammentazione se il GUID è il tuo indice cluster.
  • sì voglio GUID come chiave primaria per qualche motivo.Come impostare il valore predefinito per il GUId.Si prega di aiutare me.
  • Guid.NewGuid();
  • “per qualche motivo” non sembra che il bene di una ragione a me. Si avrà prestazioni MOLTO meglio se si utilizza una identità indice e poi c’è un’ulteriore colonna con un unico indice non cluster per la colonna GUID.
  • Ci sono state misure da ora .Il calo di prestazioni è sicuramente gestibile. È possibile utilizzare una chiave primaria non cluster e/o NEWSEQUENTIALID() per la generazione di guid. blogs.msdn.microsoft.com/sqlserverfaq/2010/05/27/…
  • Risolto questo problema, dopo lunghe ore stackoverflow.com/a/42029852/7512541

InformationsquelleAutor user2285613 | 2013-08-13



7 Replies
  1. 13

    Mi sento di raccomandare di utilizzo long per il vostro tipo di ID. Non “funziona” e ha alcuni miglioramenti delle prestazioni oltre GUID. Ma se si desidera utilizzare un GUID, si dovrebbe utilizzare un GUID sequenziale e impostare nel costruttore. Vorrei anche ID un private setter:

    public class Sample
    {
        public Sample() {
            ID = GuidComb.Generate();
        }
        [Required]
        public Guid ID { get; private set; }
        [Required]
        public string FirstName { get; set; }
    }

    Sequenziale GUID

    public static class GuidComb
        {
            public static Guid Generate()
            {
                var buffer = Guid.NewGuid().ToByteArray();
    
                var time = new DateTime(0x76c, 1, 1);
                var now = DateTime.Now;
                var span = new TimeSpan(now.Ticks - time.Ticks);
                var timeOfDay = now.TimeOfDay;
    
                var bytes = BitConverter.GetBytes(span.Days);
                var array = BitConverter.GetBytes(
                    (long)(timeOfDay.TotalMilliseconds / 3.333333));
    
                Array.Reverse(bytes);
                Array.Reverse(array);
                Array.Copy(bytes, bytes.Length - 2, buffer, buffer.Length - 6, 2);
                Array.Copy(array, array.Length - 4, buffer, buffer.Length - 4, 4);
    
                return new Guid(buffer);
            }
        }
    • 1.) Perché è un sequenziale GUID meglio? 2.) Che cosa è il “Pettine” in GuidComb? 3.) Perché 0x76c, invece di semplicemente 1900?
    • GUID sequenziale è un idea stupida. Il punto di tutta GUID è un numero così grande hai la garanzia è unico in tutti gli altri Guid in tutto il mondo quando è selezionata in modo casuale.
  2. 8

    Questo può essere fatto anche con gli attributi:

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid AddressID { get; set; }
    • Ho impostato calcolata, ma questo ha contribuito, grazie!
    • Per me non funziona con Calcolata opzione. L’Identità è l’opzione impostazioni di un valore predefinito del Database SQL -> (newid())
  3. 5

    Ho riscontrato lo stesso problema con Nlog la registrazione al database . Quello che ho fatto è volutamente aprire il file di migrazione e ha fatto le seguenti modifiche

    CreateTable(
    "dbo.Samples",
    c => new
    {
         ID = c.Guid(nullable: false,identity:true),
         FirstName = c.String(nullable: false)
    })
    .PrimaryKey(t => t.ID);

    il parametro identity consente di realtà creata la tabella con defaultvalue come newsequentialid()
    nella tabella .

    • Vota per questa risposta. Perché newsequentialid() è quindi implementato il database. Dire, se qualcuno aggiunge un nuovo record, lavorando direttamente in tavola, ma non con un Guid di errore.
  4. 4

    Se ignoriamo la politica se questa è una buona idea o meno, quindi la risposta da @TombMedia è probabile che si sta cercando.

    Se, tuttavia, è necessario aggiungere una nuova colonna a una tabella esistente e desidera specificare newId() per essere utilizzata per il valore di default, perché il campo non è nullable quindi utilizzare questo in classe di migrazione:

    AddColumn(
        "dbo.Samples",
        "UUID", 
        c => c.Guid(nullable: false, defaultValueSql: "newId()")
    );

    Nota: questa è una vecchia questione che è ancora rilevante nella EF6 e si posiziona in alto quando cercando assistenza su come utilizzare newId all’interno EF migrazioni, che è il motivo per cui questa risposta è stata aggiunta.

    • Vorrei anche rimuovere il cluster dell’indice si crea troppo, mettere il cluster in un campo che si presta per l’indicizzazione. .PrimaryKey(t => t.MemberID, clustered: false)
  5. 2

    La risposta di Paolo è a destra, ma l’attuazione del Sequenziale Guid può essere migliorata. Questa implementazione sequenziale guid incrementi più spesso e impedisce stessi numeri se creato sul server stesso.

    Per evitare link rot, codice:

    public class SequentialGuid
    {
    
        public DateTime SequenceStartDate { get; private set; }
        public DateTime SequenceEndDate { get; private set; }
    
        private const int NumberOfBytes = 6;
        private const int PermutationsOfAByte = 256;
        private readonly long _maximumPermutations = (long)Math.Pow(PermutationsOfAByte, NumberOfBytes);
        private long _lastSequence;
    
        public SequentialGuid(DateTime sequenceStartDate, DateTime sequenceEndDate)
        {
            SequenceStartDate = sequenceStartDate;
            SequenceEndDate = sequenceEndDate;
        }
    
        public SequentialGuid()
            : this(new DateTime(2011, 10, 15), new DateTime(2100, 1, 1))
        {
        }
    
        private static readonly Lazy<SequentialGuid> InstanceField = new Lazy<SequentialGuid>(() => new SequentialGuid());
        internal static SequentialGuid Instance
        {
            get
            {
                return InstanceField.Value;
            }
        }
    
        public static Guid NewGuid()
        {
            return Instance.GetGuid();
        }
    
        public TimeSpan TimePerSequence
        {
            get
            {
                var ticksPerSequence = TotalPeriod.Ticks / _maximumPermutations;
                var result = new TimeSpan(ticksPerSequence);
                return result;
            }
        }
    
        public TimeSpan TotalPeriod
        {
            get
            {
                var result = SequenceEndDate - SequenceStartDate;
                return result;
            }
        }
    
        private long GetCurrentSequence(DateTime value)
        {
            var ticksUntilNow = value.Ticks - SequenceStartDate.Ticks;
            var result = ((decimal)ticksUntilNow / TotalPeriod.Ticks * _maximumPermutations - 1);
            return (long)result;
        }
    
        public Guid GetGuid()
        {
            return GetGuid(DateTime.Now);
        }
    
        private readonly object _synchronizationObject = new object();
        internal Guid GetGuid(DateTime now)
        {
            if (now < SequenceStartDate || now > SequenceEndDate)
            {
                return Guid.NewGuid(); //Outside the range, use regular Guid
            }
    
            var sequence = GetCurrentSequence(now);
            return GetGuid(sequence);
        }
    
        internal Guid GetGuid(long sequence)
        {
            lock (_synchronizationObject)
            {
                if (sequence <= _lastSequence)
                {
                    //Prevent double sequence on same server
                    sequence = _lastSequence + 1;
                }
                _lastSequence = sequence;
            }
    
            var sequenceBytes = GetSequenceBytes(sequence);
            var guidBytes = GetGuidBytes();
            var totalBytes = guidBytes.Concat(sequenceBytes).ToArray();
            var result = new Guid(totalBytes);
            return result;
        }
    
        private IEnumerable<byte> GetSequenceBytes(long sequence)
        {
            var sequenceBytes = BitConverter.GetBytes(sequence);
            var sequenceBytesLongEnough = sequenceBytes.Concat(new byte[NumberOfBytes]);
            var result = sequenceBytesLongEnough.Take(NumberOfBytes).Reverse();
            return result;
        }
    
        private IEnumerable<byte> GetGuidBytes()
        {
            var result = Guid.NewGuid().ToByteArray().Take(10).ToArray();
            return result;
        }
    }
  6. 0

    So che la domanda è abbastanza vecchio, ma se qualcuno ha di questi problemi suggerisco di tale soluzione:

    protected Guid GetNewId()
    {
        SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["YourConnectionString"].ConnectionString);
        var query = "select newid()";
        conn.Open();
        SqlCommand com = new SqlCommand(query, conn);
        var guid = new Guid(com.ExecuteScalar().ToString());
        conn.Close();
        return guid;
    }

    Si può ottenere newid dal database SQL quando il vostro nuovo oggetto è la creazione. Per me funziona. 🙂 (ma non so, è buona prassi)

    Come si usa:

    var myNewGuidValue = GetNewId();
    • Che è la stessa di var guid = Guid.NewGuid();
  7. 0

    Quando l’utilizzo di Entity Framework Core 2.1.1 uso:

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

    Poi nella migrazione, aggiungere in defaultValueSql parametro come di seguito:

    migrationBuilder.CreateTable(
        name: "Users",
        columns: table => new
        {
             UserId = table.Column<Guid>(nullable: false, defaultValueSql: "newsequentialid()"),
             DisplayName = table.Column<string>(nullable: true)
        },
           constraints: table =>
        {
            table.PrimaryKey("PK_Users", x => x.UserId);
        });

    Questo assicura che il server sql è responsabile per la generazione di un guid sequenziale che sta per essere migliore di rotolare il vostro proprio.

    Se non si desidera che gli svantaggi dell’utilizzo sequenziale guid è possibile utilizzare “newid ()”, invece.

Lascia un commento