实体框架和全局唯一标识(GUID)

3

假设我有这段代码:

var foo = new Foo { Id = Guid.NewGuid(); }

var id = foo.Id; // have access to the id here

context.Add(foo);
context.SaveChanges();
< p > Guid.NewGuid()如何避免与数据库中已有的Guid发生冲突?如果生成的Guid已经存在于数据库中怎么办?我不明白。

使用自增ID很明显,但是在保存到数据库之前我不知道ID,这是有道理的。那么Guid是如何做到“不同”的呢?

2个回答

5

Guid.NewGuid()如何避免与我的数据库中已有的Guid发生冲突?

它并没有避免。每次生成不同的ID。实际上,生成相同的Guid的概率非常

如果生成的guid已经存在于数据库中怎么办?

如果提供的Guid值相同,则会违反主键约束。以下代码将产生“无法插入重复键”错误。

var guid = Guid.NewGuid();
context.Foos.Add(new Foo { Id = guid });
context.Foos.Add(new Foo { Id = guid });
context.SaveChanges();

注意:你可以要求Entity Framework在数据库端为你生成GUID键。使用DatabaseGenerated属性:

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

现在只需保存Foo而不手动生成键,EF将使用数据库生成的guid更新id:
var foo = new Foo { Value = 42 };
context.Foos.Add(foo); // id is 00000000-0000-0000-0000-000000000000
context.SaveChanges();     
// now id has value generated during insert 421ffa94-1970-e311-9e31-001fd09468de

谢谢。我还没有看到在主键上使用GUID相比整数有任何好处。 - undefined
1
@Bart 嗯,guid给你提供了键的唯一性。当你需要合并来自不同数据库的数据时,这真的很好。但通常我更喜欢使用int或long作为主键,因为这样的键更易读。 - undefined
谢谢!如果你正在使用EF设计器,你可以通过将StoreGeneratedPattern属性设置为Identity来获得这种行为。 - undefined
对于Code First,HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)在属性定义上工作得很好。 - undefined

1
根据MSDN,它的复制概率非常低。
备注部分:
GUID是一个128位整数(16字节),可在所有计算机和网络上使用,无论何时需要唯一标识符。这种标识符的重复概率非常低。
如果Id是你的Foo表的唯一/主键,那么如果它被重复,它将会抛出一个错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接