在Entity Framework 6中获取身份值

3

我有一个名为Task的实体,它的领域类是:

public class Task
{
    public long TaskId { get; set; }
    // blah blah
}
public DbSet<Task> Tasks { get; set; }

我希望TaskId是主键且自动递增的。因此我们有:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Task>().Property(x => x.TaskId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
    }

现在我将数据添加到数据库中。
    public bool AddTaskTable(int number,string[] params)
    {
        using (dbContext db = new dbContext())
        {
            var t = new Task { blah blah };
            db.Tasks.Add(t);
            try
            {
                db.SaveChanges();
                return true;
            }

我想要的是检索系统为将来使用而生成的TaskId。例如,如果它是另一个实体中的外键,则希望使用它。如何获取这个值?


我使用Guid,然后添加属性[DatabaseGenerated(DatabaseGeneratedOption.Identity)] - Callum Linington
EF也有一些规则,因此您不一定需要DatabaseGeneratedAttribute,尽管它不会有任何影响。 - Casey
顺便提一下,我会对命名一个类为Task感到有些谨慎,因为这可能会与异步任务产生歧义。 - Casey
4个回答

9

当您执行以下操作时:

db.SaveChanges();

实际模型已更改,并添加了ID。因此,如果在保存后读取模型,它将显示生成的更新ID。

借鉴此链中其他答案的想法,这非常符合我的答案,并解释了我的实现:

EF创建POCO(普通的CLR对象)领域模型。您的实体模型没有被处理,但是它在内存中。您的新任务T已经在内存中,因此只要成功调用SaveChanges方法,您的对象就包含自动生成的ID。

这是我的存储库实现:

public T Create<T>(T entity) where T : class
        {
            var newEntry = _dbContext.Set<T>().Add(entity);

            _dbContext.SaveChanges();

            return newEntry;
        }

在这里,实体被保存,并带着新的ID返回。

在您的实现中,请执行以下操作:

public bool AddTaskTable(int number,string[] params)
    {
        using (dbContext db = new dbContext())
        {
            var t = new Task { blah blah };
            var dbTask = db.Tasks.Add(t);
            try
            {
                db.SaveChanges();

               // task id
               dbTask.taskId;

                return true;
            }

3

在保存更改后,应填写实体的 TaskId 属性。

如果您需要在保存更改之前使用它(不是实际的 Id,而是需要将此对象用作外键属性),则需要使用导航属性并建模您的关系。


0
我认为在添加任务时,您可以检索到TaskId,类似于以下方式:
public int AddTaskTable(int number,string[] params)
    {
        using (dbContext db = new dbContext())
        {
            var t = new Task { blah blah };
            db.Tasks.Add(t);
            try
            {
                db.SaveChanges();
                var newTaskId = dbContext
                                    .Tasks
                                    .OrderByDescending(x => x.TaskId)
                                    .FirstOrDefault().TaskId;
                return newTaskId;
             }
         }
    }

它将始终为您提供TaskId的精确值。


2
不要这样做 - 在 db.SaveChanges() 调用和下一行之间,很容易有另一个线程向表中添加行。这将为您的对象 ID 提供无效值。EntityFramework 应该在保存实体时自动设置主 ID。 - matt
我同意这是一个不好的做法。它需要比必要的更多的数据库查询。 - Callum Linington

0

EF创建POCO(Plain Old CLR Objects)领域模型。您的实体模型未被释放,但它在内存中。您的新任务T已经在内存中,因此一旦SaveChanges方法成功调用,您的对象也将包含自动生成的ID。


我在你的回答中没有看到POCO的解释。这是一个需要与解决方案一起解释的概念。 - Palak Bhansali
我会将你的答案放在我的答案中,以确保被接受的答案包含所有相关信息。 - Callum Linington
你的回答也很有帮助。我看到很多帖子都包含了许多相似的解决方案,这些解决方案大多数时候成为了有用的资源 :) - Palak Bhansali

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