在context.SaveChanges()之前获取新创建的实体的数据库ID(IDENTITY COLUMN)

时间:2013-06-04 12:31:38

标签: sql-server sql-server-2008 entity-framework entity-framework-4 ado.net

是否可以使用Entity Framework为数据库中的待添加行保留IDENTITY值?

在我对ObjectContext.SaveChanges的覆盖中,我想做这样的事情:

public override int SaveChanges(SaveOptions options)
{
    var affectedEntities = ObjectStateManager.GetObjectStateEntries(
        EntityState.Added |
        EntityState.Modified |
        EntityState.Deleted);

    foreach (var entry in affectedEntities)
    {
        var type = GetObjectType(entry.Entity.GetType());

        if (entry.State == EntityState.Added)
        {
            // log the creation of the new entity into a log file
            // or a different table. For this, I need the newly
            // created entity's ID. Is it possible?
        }
    }

    return base.SaveChanges(options);

    // if I check for ObjectState here, i.e. after SaveChanges, 
    // it won't work? Because once the changes are committed to the database
    // the newly added object's state would no longer remain
    // Added.
}

1 个答案:

答案 0 :(得分:1)

您无法要求数据库预先分配ID。你有2个选择

  1. 实施您自己的身份服务器
  2. 在数据写入数据库后获取id
  3. 以下是选项2的几个示例。它们都做同样的事情 - 在调用SaveChanges()之前构建一个已添加项的列表,并在之后迭代它们。

    public interface IIDentifiable
    {
        int id { get; set; }
    }
    
    public override int SaveChanges()
    {
        ChangeTracker.DetectChanges();
        List<IIDentifiable> addedObjects = GetNewEntries();
        int result = base.SaveChanges();
        foreach (IIDentifiable o in addedObjects)
        {
            //log o.id
        }
        return result;
    }
    
    private List<IIDentifiable> GetNewEntries()
    {
        var result = (
            from e in ChangeTracker.Entries()
            where e.State == System.Data.EntityState.Added
            select e.Entity)
            .OfType<IIDentifiable>()
            .ToList();
    
        return result;
    }
    

    IIDentifiable的缺点是获得其他详细信息,例如Type等。

    第二个选项是做同样的事情,但使用dynamic代替IIDentifiable

    public override int SaveChanges()
    {
        ChangeTracker.DetectChanges();
        List<dynamic> addedObjects = GetNewEntries();
        int result = base.SaveChanges();
        foreach (dynamic o in addedObjects)
        {
            //log o.id
            //log o.GetType()
        }
        return result;
    }
    
    private List<dynamic> GetNewEntries()
    {
        var result = (
            from e in ChangeTracker.Entries()
            where e.State == System.Data.EntityState.Added
            select e.Entity)
            .ToList();
    
        return result;
    }