Entity framework 调用SaveChanges()之前添加的实体的访问id

Entity framework 调用SaveChanges()之前添加的实体的访问id,entity-framework,savechanges,audit-logging,Entity Framework,Savechanges,Audit Logging,我使用的是EF 4.3.1,我覆盖了上下文中的SaveChanges(),这样我就可以获得对象及其状态的列表,并在我的审核日志表中创建条目。我需要将记录的id存储在审核日志表中,以便对其进行引用。插入记录时会出现问题,因为在保存id之前,我无法访问该id。在那一点上有没有办法得到身份证 public override int SaveChanges() { ChangeTracker.DetectChanges(); var objectStateManager

我使用的是EF 4.3.1,我覆盖了上下文中的SaveChanges(),这样我就可以获得对象及其状态的列表,并在我的审核日志表中创建条目。我需要将记录的id存储在审核日志表中,以便对其进行引用。插入记录时会出现问题,因为在保存id之前,我无法访问该id。在那一点上有没有办法得到身份证

public override int SaveChanges()
{
        ChangeTracker.DetectChanges();

        var objectStateManager = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager;
        var modifiedAuditableEntities = objectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added).Where(e => (IAuditable)e.Entity != null);

        foreach (var entry in modifiedAuditableEntities)
        {
            var entity = (IAuditable)entry.Entity;

            if (entity != null)
            {
                switch (entry.State)
                {
                    case EntityState.Added:
                        entity.IsAdded = true;
                        break;
                    case EntityState.Deleted:
                        entity.IsDeleted = true;
                        break;
                    case EntityState.Modified:
                        entity.IsModified = true;
                        break;
                }

                this.EntitySet<AuditLogEntry>().Add(this.auditLogService.CreateAuditLogEntryForEntity((IAuditable)entry.Entity));
            }
        return base.SaveChanges();
}
public override int SaveChanges()
{
ChangeTracker.DetectChanges();
var objectStateManager=((IObjectContextAdapter)this).ObjectContext.objectStateManager;
var modifiedAuditableEntities=objectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added)。其中(e=>(IAuditable)e.Entity!=null);
foreach(modifiedAuditableEntities中的var条目)
{
var entity=(IAuditable)entry.entity;
如果(实体!=null)
{
开关(进入状态)
{
案例实体状态。添加:
entity.IsAdded=true;
打破
案例实体状态。已删除:
entity.IsDeleted=true;
打破
案例实体状态。已修改:
entity.IsModified=true;
打破
}
this.EntitySet().Add(this.auditLogService.CreateAuditLogEntryForEntity((IAAudiTable)entry.Entity));
}
返回base.SaveChanges();
}

Id该Id是由数据库生成的整数,在调用“保存更改”之前无法获取该Id。可能的解决方案包括:

  • 触发
  • 使用guid作为主键
  • 使用不由数据库管理的密钥生成策略(NHibernate中的HiLo)
  • 首先调用base.SaveChanges(),然后检查结果

如果您的目标是同时创建保存和审核日志,则可以将其包装在事务作用域中,使您的方法具有原子性

    public override int SaveChanges()
    {
        ChangeTracker.DetectChanges();
        using (var scope = new TransactionScope())
        {
            var objectStateManager = ((IObjectContextAdapter) this).ObjectContext.ObjectStateManager;
            var modifiedAuditableEntities =
                objectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added).Where(
                    e => (IAuditable) e.Entity != null);
            var result = base.SaveChanges();
            foreach (var entry in modifiedAuditableEntities)
            {
                var entity = (IAuditable) entry.Entity;

                if (entity != null)
                {
                    switch (entry.State)
                    {
                        case EntityState.Added:
                            entity.IsAdded = true;
                            break;
                        case EntityState.Deleted:
                            entity.IsDeleted = true;
                            break;
                        case EntityState.Modified:
                            entity.IsModified = true;
                            break;
                    }

                    this.EntitySet<AuditLogEntry>().Add(
                        this.auditLogService.CreateAuditLogEntryForEntity((IAuditable) entry.Entity));
                }
            }
            base.SaveChanges();

            scope.Complete();
            return result;
        }
    }
public override int SaveChanges()
{
ChangeTracker.DetectChanges();
使用(var scope=new TransactionScope())
{
var objectStateManager=((IObjectContextAdapter)this).ObjectContext.objectStateManager;
var modifiedAuditableEntities=
objectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added)。其中(
e=>(IAuditable)e.实体!=null);
var result=base.SaveChanges();
foreach(modifiedAuditableEntities中的var条目)
{
var entity=(IAuditable)entry.entity;
如果(实体!=null)
{
开关(进入状态)
{
案例实体状态。添加:
entity.IsAdded=true;
打破
案例实体状态。已删除:
entity.IsDeleted=true;
打破
案例实体状态。已修改:
entity.IsModified=true;
打破
}
this.EntitySet().Add(
this.auditLogService.CreateAuditLogEntryForEntity((IAuditable)entry.Entity));
}
}
base.SaveChanges();
scope.Complete();
返回结果;
}
}

我建议在数据库级别使用存储过程来执行插入/审核功能(以及其他数据库更改),并撤销用户的插入/更新/删除权限。因此,您可以保证更新过程和审核表的完整性。

它是如何获取其ID的?如果它是由数据库生成的,则它甚至在由数据库生成的savechangesys之前不存在。这是一个问题。我可以为基于实体状态审核日志,然后将实际实体保存到数据库中,然后可能使用实体id更新审核日志条目。但是,我如何将保存的条目链接到审核日志条目……这是我的问题……有什么想法吗?谢谢!使用事务作用域有什么缺点吗?另外,我如何获取实体id我的日志记录?在我的auditlogservice中,我可以只使用logEntry.EntityId=entry.Entity.Id吗?这足以连接它吗?我经历的唯一缺点是,您可能会调用,但这取决于您具体执行的操作。在调用第一个SaveChanges后,将加载条目的Id属性。抱歉,我没有遵循…所以在第一次SaveChanges()之前在我的服务中设置logEntry.EntityId=entry.Entity.Id调用的不会设置id?您希望在第一次保存更改之后,在第二次保存更改之前设置id。因为它包装在事务作用域中,所以在完成作用域之前不会提交更改,因此您不必担心并发性和其他问题。因此,SaveChanges()的位置实际上是基础。SaveChanges()?但此时该项尚未推送到db,因此它仍然没有id?在SaveChanges()和scope.Complete()之间,我是否需要在auditlogEntry上手动设置id?我在SaveChanges()上方的行中进行了此操作…似乎之后需要进行此操作?谢谢!我如何检查base.SaveChanges()的结果?据我所知,实体将被更改。