EF Code-first,插入时如何将主键插入另一个字段?

EF Code-first, how to insert primary key to another field when inserting?

这是我要插入数据库的实体:

public sampleEntity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int PrimaryKey { get; set; }

    [Required]
    public string Ticket { get; set; }
}

Ticket 的格式类似于

string.Format("{0:yyyyMMdd}-{1}", DateTime.Now, PrimaryKey);

因此,当我将此实体添加到上下文时,primaryKey 始终为 0,因此 Ticket 值始终为“20170315-0”

目前我的解决方案是

// first add row and save
SampleEntity sample = new SampleEntity {
    Ticket=DateTime.Now.ToString("yyyyMMdd")
};
context.Samples.Add(sample);
context.SaveChanges();

// then find it out and update
var latest = context.Samples.OrderByDecending(p => p.PrimaryKey).First();
latest.Ticket += sample.PrimaryKey.ToString();
context.SaveChanges();

如何在SaveChanges()没有更新的情况下根据primaryKey值设置Ticket值?

您有 DatabaseGeneratedOption.Identity 主键选项。

这意味着只有 SQL服务器知道那个ID,并且那个知识在实际只有的那一刻具体化INSERT 进入数据库(因为数据库中的相关列是某种 IDENTITY 列)。

例如,考虑两个同时向数据库中插入新记录的应用程序 - 它们将接收不同的密钥,但您无法确定哪个应用程序接收哪个密钥。

Entity Framework 将为 SaveChanges 生成两个请求 - 第一个是 INSERT,另一个是 SELECT 以接收生成的密钥。

只有在那之后,您的代码才会知道实际密钥并能够将其用于您的机票计算 - 所以基本上您无法避免使用 EF 的另一个 UPDATE

不过,您可以做的是更改由您的代码而不是数据库控制的内容的主键类型 - 例如,随机 GUID;在这种情况下,您将知道 ID before insert 并且可以以任何您想要的方式使用它。

但是对主键使用 GUID 会导致其他并发症,这在大多数情况下是不值得的,比如非顺序插入会导致经常重建索引,仍然有一定的键冲突可能性,更多 space 保留专栏等

另一种选择是在应用程序中为票证列设置 计算 列或类似逻辑,因此您将有单独的日期列和单独的 ID 列,但对于票证,您要么始终在需要时应用 concat 逻辑,创建仅 return 值的计算列(因此对于数据库和 EF 是只读的)。