在Entity Framework中自动生成非主键的GUID列

5
我正在从现有的模型和数据库转换到Entity Framework。在该数据库中,有几个具有GUID列的表,这些列不是主键(或根本不是键!)。每个表都有一个ID列。GUID列上定义了ROWGUIDCOL属性以及一个DEFAULT(newid())。
现在,当我插入到数据库时,我得到了这一列的所有零。
我尝试使用数据注释:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Guid {get; set;}

这样做的问题在于它会丢失我的ID列上的身份属性(并给我插入错误)。此外,我注意到对于以下迁移,EF实际上为up和down方法生成了相同的SQL语句:
public override void Up()
{

    AlterColumn("dbo.Client", "Guid", c => c.Guid(nullable: false, identity: true));
}

public override void Down()
{
    AlterColumn("dbo.Client", "Guid", c => c.Guid(nullable: false));
}

使用生成的SQL:

ALTER TABLE [dbo].[Client] ALTER COLUMN [Guid] [uniqueidentifier] NOT NULL

为什么上述迁移对两个语句生成相同的SQL?如何让EF生成GUID?我可以/必须在客户端(代码)空间中执行此操作吗?如果我必须这样做,如何确保跨表唯一性?


我不了解EF,但是看起来你混淆了标识属性和默认值。在SQL Server中,GUID数据类型不能具有“identity”属性。 - jazzytomato
你的主键是否使用了[Key]属性进行装饰? - Keith
1
应该使用DatabaseGenerationOption.Identity来设置自增列。你尝试过使用DatabaseGenerationOption.Computed吗?它可以防止EF在插入列时发送值,并且在SaveChanges时可以正确地获取数据库生成的值。 - ESG
@TheVedge - 看起来你是对的。我一开始没有使用它的原因是这里的文档[http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.schema.databasegeneratedoption%28v=vs.110%29.aspx],特别是“当插入或更新行时,数据库会生成一个值。”我认为这意味着GUID将在每次更新时重新生成,但事实并非如此(他们只是意味着它可能会更新,由DB决定)。如果你想提交答案,我会很乐意接受。 - Stephen Panzer
@StephenPanzer完成。这个东西需要一种将评论推广为解决方案的方法! - ESG
@StephenPanzer 您读得确切无误,Identity 也适用于具有默认约束的非标识列。如果这不起作用,并且 Computed 起作用,请坚决使用它,但请注意这是一种解决方法,并检查生成的 SQL 将(或者至少应该)向您显示 EF 将在每次保存后检索新值。 - user743382
2个回答

2

应该使用DatabaseGenerationOption.Identity来表示自增列。

尝试使用DatabaseGenerationOption.Computed替代。这样可以防止EF在插入列时发送值,并且在SaveChanges时正确获取数据库生成的值。


有没有一种方法可以在数据库优先和EF继承中实现这个设置,自动将其创建到Poco类中,而不是手动设置注释? - Emil
我对db first不是特别熟悉,但如果它确实这样做了,我会感到惊讶的。 - ESG

1
我尝试将预先存在的ID标识列转换为GUID时,遇到了一些错误。计算无法起作用,设置为身份也无法起作用。将其设置为DatabaseGeneratedOption.None会导致错误,指出我无法在必需字段中插入空值。我在构造函数中有一个NewGuid生成,但似乎也没有帮助。
为了使其正常工作,我删除了我的迁移.cs文件和数据库,然后使用数据注释,通过将新的GUID ID设置为Key、DatabaseGeneratedOption.None,并在ID属性后面放置一个后备字段,成功地绕过了系统。这迫使我的Getter查看私有字段,确定它是否为Guid.Empty,如果是,则为我生成一个新的GUID。
    private Guid id = Guid.Empty;

    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    [HiddenInput(DisplayValue = false)]
    public Guid CompanyId
    {
        get
        {
            if(id==Guid.Empty)
                id = new Guid();
            return id;
        }
        set { id = value; }
    }

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