11

私はasp.net mvc4 sampleを作成しています。これは、datacontextのSampleテーブルのGUIDとしてID列を作成しました。エンティティフレームワークでGUIDのNewId()を設定する方法

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

これは

​​

Idが00000000-0000-0000-0000-000000000000を渡すエンティティテーブルです。

設定方法newid()からGUIDまで設定する必要があります。

+1

は、あなたが使用したいあなたは確かにあります主キーとしてのGUIDを使用すると、GUIDがクラスタード・インデックスの場合、断片化のために大きなパフォーマンス上の問題が発生します。 –

+0

はい私はGUIDを何らかの理由でプライマリキーとして使用したいのですが、GUIdのデフォルト値を設定する方法を教えてください。 – user2285613

+0

Guid.NewGuid(); –

答えて

13

あなたのIDタイプにはlongを使用することをお勧めします。これは「うまくいく」と、GUIDよりもパフォーマンスが向上しています。 GUIDを使用する場合は、Sequential GUIDを使用し、コンストラクタでそれを設定する必要があります。

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

シーケンシャル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); 
     } 
    } 
+0

)1.なぜ連続したGUIDが優れていますか? 2.)GuidCombの "Comb"とは何ですか? 3.)単に '1900'の代わりに' 0x76c'を使うのはなぜですか? – Sinjai

2

ポールの答えは正しいですが、シーケンシャルのGuidの実装を向上させることができます。また、私はID privateセッターになるだろう。 This implementation of sequential guidは、同じサーバー上に作成された場合、同じ回数が増えることを防止します。 link rotを防ぐために

、コード:

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; 
    } 
} 
5

私はNlogがデータベースにログインすると、同じ問題が発生しました。私がやったことは、意図的に移行ファイルを開くことで、次は

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

を変更しなかったIdentityパラメータには、実際にテーブルにnewsequentialid() としてdefaultvalueでテーブルを作成しました。

+0

この回答のUpvote。 'newsequentialid()'がデータベース上で実装されるためです。テーブル上で直接作業して新しいレコードを追加すると、重複したGuidエラーで失敗しません。 – Blaise

0

私はその質問がかなり古いですけど、誰かがこのような問題を持っている場合、私は、このような解決策を提案する:

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; 
} 

新しいオブジェクトが作成されているときは、SQLデータベースからNEWIDを得ることができます。私にとってはうまくいく。 :)(私はそれが良い習慣であるかわからない)どのようにそれを使用

を:これは属性でもを行うことができます

var myNewGuidValue = GetNewId(); 
+0

これはvar guid = Guid.NewGuid()と同じです。 –

3

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

私はそれを計算するように設定しましたが、これはおかげで助かりました! – Nick

関連する問題