简体   繁体   English

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

[英]Get the database ID (IDENTITY COLUMN) of newly created entity before context.SaveChanges()

Is it possible to reserve an IDENTITY value for a to-be-added row in the database using Entity Framework? 是否可以使用Entity Framework在数据库中为要添加的行保留IDENTITY值?

In my override of ObjectContext.SaveChanges , I want to do something like this: 在对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.
}

You can't ask the database to preallocate the id's. 您不能要求数据库预先分配ID。 You have 2 options 您有2个选择

  1. implement your own identity server 实现自己的身份服务器
  2. get the id's after the data has been written to the database 将数据写入数据库后获取ID

Here's a couple of examples of option 2. They both do the same thing - build a list of added items before the call to SaveChanges() and iterate over them after. 这是选项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;
}

the drawback of IIDentifiable is getting other details such as Type etc. IIDentifiable的缺点是获取其他详细信息,例如Type等。

The second option is to do the same thing but use dynamic instead of IIDentifiable 第二个选项是做相同的事情,但使用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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM