【问题标题】:Generate Guid on database but only when not set in entity在数据库上生成 Guid,但仅在实体中未设置时
【发布时间】:2016-09-22 15:25:48
【问题描述】:

我有一个案例,我需要添加一个非主键的 Guid 属性,并且可以与表中的多个对象共享。

我想做的是:

  • 当我不给它一个值时在数据库上生成 Guid
  • 当我有值时设置一个 Guid(而不是生成它)

这两项都将仅在插入时完成,更新不会触及这些值。

我尝试过的:

  • 添加 [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 属性:仅在我不需要手动设置 Guid 时有效
  • 添加 [DatabaseGenerated(DatabaseGeneratedOption.Computed)] 属性:当我不手动设置 Guid 时不起作用

我已经看过很多关于这个主题的文章,最接近的应该是这篇文章: http://www.davepaquette.com/archive/2012/09/23/calculated-columns-in-entity-framework-code-first-migrations.aspx

但我们不会(也不会)在我们的项目中使用迁移,所以这似乎不合适。

或者这个 SO question,但这意味着在 .Net 中生成 Guid(至少在我看来,这似乎不是很干净):EF, Code First - How to set a custom Guid identity value on insert

有没有办法生成 Guid 数据库端,并在需要时先在 EF 代码中设置它?

如果没有,有什么好的选择?在 .Net 端生成 Guid 真的是个坏主意吗? (如果没有其他可能,我可以这样做)

【问题讨论】:

  • 您可以编辑您的迁移并设置默认值 newid(),并将其标记为 databsegeneratedoption.identity
  • @HadiHassan 实际上我们不会(也不会)在这个项目中使用迁移...你知道另一种设置“newid()”的方法吗?
  • 我认为您只能通过设置 guid 的插入触发器来执行此操作,以防提供空值。

标签: c# ef-code-first entity-framework-6 guid


【解决方案1】:

我假设你使用的是 MS-SQL ,那么你可以执行以下操作

使用执行命令

public class YourDbContext: DbContext
{
     public YourDbContext():base("ConnectionString")
     {              
            if (Database.Exists())
            {                   
                Database.ExecuteSqlCommand("if object_id('CT_DefaultGuid') is null alter table YourTable add constraint CT_DefaultGuid default newid() for YourColumn");
            }
     }
}

要从 .Net 设置 Id,您可以执行以下操作

  • 创建包含 Id 属性的基本实体
  • 在构造函数中检查 Id 是否为空,然后对其进行初始化
  • 让你必须继承的所有实体都继承自这个类

你的基类应该是这样的

public class BaseEntity
{
     public BaseEntity()
     {
          if(Id==Guid.Empty)
               Id = Guid.NewGuid();
     }

     public Guid Id{get;set;}
}

将迁移用于现有数据库

  • 来自 PMC => Enable-migrations
  • 来自 PMC => Add-Migration "FirstRun"
  • 打开生成的迁移文件并确保清空Up 和Down 方法(这不会对数据库应用任何更改)
  • 在Up方法中使用Sql("")方法添加对应的alter column fluent code
  • 来自 PMC => Update-Database -Script ,确保生成的只有 sql 语句是 alter table 语句
  • 来自 PMC => 一旦您确定所需的语句是唯一出现在 SQL 脚本中的语句,然后应用:Update-Database。

你的班级应该是这样的

public class FirstRun : DbMigration
{    public override void Up()
     {
        Sql("alter table YourTable add constraint CT_DefaultGuid default newid() for YourColumn");
     }
}

我推荐最后一种方法,它会执行一次,您可以稍后将更改添加到您的数据库中。

希望对你有帮助

【讨论】:

  • 谢谢,你猜对了,这确实有帮助,你能解释一下吗?这是否也意味着每次创建上下文时都会进行此检查? (可能有很多)
  • 是的,它会在每次创建上下文时发生,这就是我在 cmets 中建议使用迁移的原因,迁移将为您的代码增加巨大的潜力,例如创建视图和播种数据。
  • 这段代码第一次完全执行并且会延迟执行 if 语句,如果你不想往返数据库,你可以用存储在appsettings 并在第一次运行后更新它,这将阻止代码稍后执行
  • 是的,迁移本来是一件好事,我同意你的看法,但项目已经晚了,我知道我们不会调查这个功能,因为我们都不熟悉它。
  • 这似乎是一个很好的解决方案,我明天试试(现在我正在.Net 端生成这些 guid)
猜你喜欢
  • 1970-01-01
  • 2012-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-20
  • 2015-02-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多