2017-04-13 6 views
0

私はモデルでプライマリキー名を取得しようとしていますが、データベースはFluent APIで設計されており、見つかったすべての例はDataAnnotationで設計されています。C# - 監査ログ - Fluent APIで設計されたモデルからPK名を取得するには?

DbContextのSaveChanges()をオーバーライドして監査ログを作成しています。

これは、監査ログを保存するコードです。

private List<AuditLogModel> GetAuditRecordsForChange(DbEntityEntry dbEntry, int? id_usuario = null) 
    { 
     List<AuditLogModel> result = new List<AuditLogModel>(); 

     DateTime changeTime = DateTime.Now; 

     // Get the Table() attribute, if one exists 
     TableAttribute tableAttr = dbEntry.Entity.GetType().GetCustomAttributes(typeof(TableAttribute), false).SingleOrDefault() as TableAttribute; 

     // Get table name (if it has a Table attribute, use that, otherwise get the pluralized name) 
     string tableName = tableAttr != null ? tableAttr.Name : dbEntry.Entity.GetType().Name; 

     // Get primary key value (If you have more than one key column, this will need to be adjusted) 
     //string keyName = dbEntry.Entity.GetType().GetProperties().Single(p => p.GetCustomAttributes(typeof(KeyAttribute), false).Count() > 0).Name; 
     var oc = ((IObjectContextAdapter)this).ObjectContext; 
     EntityKey key = oc.ObjectStateManager.GetObjectStateEntry(dbEntry.Entity).EntityKey; 
     string keyName = key.EntitySetName; 

     if (dbEntry.State == EntityState.Added) 
     { 
      // For Inserts, just add the whole record 
      // If the entity implements IDescribableEntity, use the description from Describe(), otherwise use ToString() 
      result.Add(new AuditLogModel() 
      { 
       Id_Usuario = id_usuario, 
       Id_Registro = (int)dbEntry.CurrentValues.GetValue<object>(keyName), // Again, adjust this if you have a multi-column key 
       EventoTipo = "I", // INSERT 
       Tabela = tableName, 
       NovoValor = dbEntry.CurrentValues.ToObject().ToString() 
      }); 
      //NovoValor = (dbEntry.CurrentValues.ToObject() is IDescribableEntity) ? (dbEntry.CurrentValues.ToObject() as IDescribableEntity).Describe() : dbEntry.CurrentValues.ToObject().ToString() 
     } 

     // Otherwise, don't do anything, we don't care about Unchanged or Detached entities 

     return result; 
    } 

ID_Registroプロパティを参照すると、これは操作のIDを受け取ります。 この行では、keyNameは主キーフィールドの名前を指定する必要があります。 この行の結果、保存されるIDが得られます。 しかし、このフィールドはプライマリキーが見つからないためエラーです。

どうすればこの問題を解決できますか?

はEDIT:

これがモデルです。 Codigoが主キーです。 HasKeyが主キーとしてCodigoを決定し、モデルにはDataAnnotationがない

public AcessoLogMapping() 
    { 
     ToTable("TB_ACESSO_LOG"); 
     HasKey(x => x.Codigo); 

     Property(x => x.Codigo).HasColumnName("ID_ACESSO_LOG") 
      .HasColumnType("INT") 
      .IsRequired(); 

     Property(x => x.CodigoUsuario).HasColumnName("ID_USUARIO_ACESSO_LOG") 
      .HasColumnType("INT") 
      .IsRequired(); 

     HasRequired(x => x.Usuario) 
      .WithMany() 
      .HasForeignKey(x => x.CodigoUsuario) 
      .WillCascadeOnDelete(false); 

     Property(x => x.Horario).HasColumnName("HORARIO_ACESSO_LOG") 
      .HasColumnType("DATETIME") 
      .IsRequired(); 

     Property(x => x.IP).HasColumnName("IP_ACESSO_LOG") 
      .HasColumnType("VARCHAR") 
      .HasMaxLength(180) 
      .IsRequired(); 
    } 

注:

public sealed class AcessoLogModel 
{ 
    public int Codigo { get; set; } 
    public int CodigoUsuario { get; set; } 
    public UsuarioModel Usuario { get; set; } 
    public string IP { get; set; } 
    public DateTime Horario { get; set; } 
} 

この

マッピングです。

答えて

0

これは私のために働くようだ:

Id_Registro = entry.State == EntityState.Added ? null : ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity).EntityKey.EntityKeyValues[0].Value.ToString() 
+0

これとNullReferenceExceptionをスローします。 EntityKeyValuesはnullです。モデルとマッピングを説明に追加しました。多分役立つかもしれません。 –

関連する問題