Asp.net mvc 如何在实体框架中为GUID设置NewId()

Asp.net mvc 如何在实体框架中为GUID设置NewId(),asp.net-mvc,asp.net-mvc-3,asp.net-mvc-4,entity-framework-5,Asp.net Mvc,Asp.net Mvc 3,Asp.net Mvc 4,Entity Framework 5,我正在创建asp.net mvc4示例。在此示例中,我在datacontext的示例表中创建了Id列作为GUID public class Sample { [Required] public Guid ID { get; set; } [Required] public string FirstName { get; set; } } 这是实体表 CreateTable( "dbo.Samples", c => new { ID = c.G

我正在创建asp.net mvc4示例。在此示例中,我在datacontext的示例表中创建了Id列作为GUID

public class Sample
{
    [Required]
    public Guid ID { get; set; }
    [Required]
    public string FirstName { get; set; }
}
这是实体表

CreateTable(
"dbo.Samples",
 c => new
 {
     ID = c.Guid(nullable: false),
     FirstName = c.String(nullable: false)                   
 })
 .PrimaryKey(t => t.ID);
Id通行证00000000-0000-0000-0000-000000000000


如何将
newid()
设置为
GUID
以及我必须设置的位置。

我建议只使用
long
作为ID类型。它“只工作”于GUID,并且比GUID有一些性能提升。但是,如果要使用GUID,应该使用并在构造函数中设置它。我也会让ID成为一个
private
setter:

public class Sample
{
    public Sample() {
        ID = GuidComb.Generate();
    }
    [Required]
    public Guid ID { get; private set; }
    [Required]
    public string FirstName { get; set; }
}
顺序GUID
Paul的答案是正确的,但是顺序Guid的实现可以改进。如果在同一台服务器上创建相同的数字,则增加的频率会更高,并防止出现相同的数字

为了防止这种情况,代码:

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;
    }
}
公共类顺序GUID
{
public DateTime SequenceStartDate{get;private set;}
public DateTime SequenceEndDate{get;private set;}
私有常量int NumberOfBytes=6;
private const int PermutationsOfAByte=256;
private readonly long _maximumPermutations=(long)Math.Pow(PermutationsOfAByte,NumberOfBytes);
私有长序列;
公共序列GUID(DateTime sequenceStartDate、DateTime sequenceEndDate)
{
SequenceStartDate=SequenceStartDate;
SequenceEndDate=SequenceEndDate;
}
公共顺序GUID()
:这(新日期时间(2011年10月15日),新日期时间(2100年1月1日))
{
}
private static readonly Lazy InstanceField=new Lazy(()=>new SequentialGuid());
内部静态顺序GUID实例
{
得到
{
返回InstanceField.Value;
}
}
公共静态Guid NewGuid()
{
返回Instance.GetGuid();
}
公共时间跨度时间序列
{
得到
{
var ticksPerSequence=TotalPeriod.Ticks/_maximumPermutations;
var结果=新的时间跨度(ticksPerSequence);
返回结果;
}
}
公共时间跨度总周期
{
得到
{
var结果=SequenceEndDate-SequenceStartDate;
返回结果;
}
}
私有长GetCurrentSequence(日期时间值)
{
var ticksUntilNow=value.Ticks-SequenceStartDate.Ticks;
var结果=((十进制)ticksUntilNow/TotalPeriod.Ticks*_maximumPermutations-1);
返回(长)结果;
}
公共Guid GetGuid()
{
返回GetGuid(DateTime.Now);
}
私有只读对象_synchronizationObject=新对象();
内部Guid GetGuid(现在是日期时间)
{
如果(现在SequenceEndDate)
{
返回Guid.NewGuid();//超出范围,请使用常规Guid
}
var序列=GetCurrentSequence(现在);
返回GetGuid(序列);
}
内部Guid GetGuid(长序列)
{
锁定(_synchronizationObject)
{

if(sequence我在Nlog日志记录到数据库时遇到了同样的问题

CreateTable(
"dbo.Samples",
c => new
{
     ID = c.Guid(nullable: false,identity:true),
     FirstName = c.String(nullable: false)
})
.PrimaryKey(t => t.ID);
identity参数实际使用
defaultvalue
作为
newsequentialid()

在表中。

我知道这个问题已经很老了,但如果有人有这样的问题,我建议这样的解决方案:

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数据库中获取新ID。对我来说,它可以工作。:(但我不知道这是一种好的做法)

如何使用它:

var myNewGuidValue = GetNewId();

这也可以通过属性完成:

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

如果我们忽略了周围的政治,不管这是不是一个好主意,那么答案很可能就是你在寻找的

但是,如果需要向现有表中添加一个新列,并且由于字段不可为Null而希望指定用于默认值的newId(),请在迁移类中使用此字段:

AddColumn(
    "dbo.Samples",
    "UUID", 
    c => c.Guid(nullable: false, defaultValueSql: "newId()")
);
注意:这是一个在EF6中仍然相关的老问题,在寻找如何在EF迁移中使用newId的帮助时排名很高,这就是为什么添加了这个答案


使用实体框架Core 2.1.1时,我使用:

[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid UserId { get; set; }
然后在迁移中,添加defaultValueSql参数,如下所示:

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);
    });
migrationBuilder.CreateTable(
名称:“用户”,
列:表=>new
{
UserId=table.Column(nullable:false,defaultValueSql:“newsequentialid()”,
DisplayName=table.Column(可空:true)
},
约束:表=>
{
表.PrimaryKey(“PK_用户”,x=>x.UserId);
});
这确保了sql server负责生成顺序guid,这将比您自己的guid更好


如果您不想使用顺序GUID的缺点,可以改用“newid()”。

是否确实要将GUID用作主键,如果GUID是聚集索引,则会由于碎片而导致严重的性能问题。是的,出于某种原因,我想将GUID用作主键。如何设置GUID的默认值。请帮助我。“出于某种原因"对我来说,这听起来不是一个很好的理由。如果使用标识索引,然后为GUID列添加一个具有唯一非聚集索引的附加列,则性能会好得多。到目前为止,已经有了度量。性能影响肯定是可管理的。您可以使用非聚集主键和/或NEWSEQUENTIALID()用于生成guid。在长时间投票后解决了此问题。因为
newsequentialid()
随后在数据库上实现。例如,如果有人通过直接处理表来添加新记录,它不会因重复的guid错误而失败。这与var guid=guid.NewGuid()相同;1.)为什么顺序GUID更好?2.)在
GuidComb
?3.)为什么
0x76c
而不是简单的
1900
?顺序GUID是一个愚蠢的想法。GUID的关键是它的数量如此之大,你可以保证它是正确的
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);
    });