3

私はこれを達成するためにさまざまなアプローチをたくさん探してきました。しかし、パフォーマンスのログ記録とデバッグに焦点を当てた、多くのサードパーティのインストールなしでこれを行う方法について、良い簡単な例をまだ見つけていません。

すべての変更をデータベースに簡単に記録する方法と、新しい行が追加されたときの方法を探しています。コントローラーが呼び出されたアクションを格納する独自のテーブルが必要です/または単にデータベーステーブルで追跡できます。そして、どのフィールドが更新または追加されたか。私は次のようなテーブルを描いています:

ID - ACTION/TABLE/METHOD - ID -  TYPE - DETAILS - CREATED BY - TIMESTAMP

 x - TableName/ActionResult/JsonResult/ - ID of the new or updated item - updated or new - details on what have changed or created - user.identity - timestamp

そのため、特定のビューごとにログ テーブルを表示でき、そのアイテムの履歴や変更されたフィールドなどを確認できます。

ここで一番下の提案を見ました: MVC 4変更ログを実装する方法は? 私の SQL データベースは SQL Service Broker をサポートしていないため、SQL にトリガーを追加することから始めたくありません。

私は MVC 5.2 と EF 6.0 を使用しているので、Database.Log プロパティを調べましたが、目的を達成するための適切な方法を設定する方法についてのガイダンスが本当に必要です。

4

1 に答える 1

4

現在、自分のニーズに合わせて変更しているソリューションを見つけました。

コードは次のとおりです。

での SaveChanges クラスのオーバーライド

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>

これらのメソッドを追加します。

public async Task SaveChangesAsync(string userId)
        {

            // Get all Added/Deleted/Modified entities (not Unmodified or Detached)
            foreach (var ent in this.ChangeTracker.Entries().Where(p => p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified))
            {
                // For each changed record, get the audit record entries and add them
                foreach (Log x in GetAuditRecordsForChange(ent, userId))
                {
                    this.Log.Add(x);
                }
            }

            // Call the original SaveChanges(), which will save both the changes made and the audit records
            await base.SaveChangesAsync();
        }

        private List<Log> GetAuditRecordsForChange(DbEntityEntry dbEntry, string userId)
        {
            List<Log> result = new List<Log>();

            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;

            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 Log()
                {
                    LogID = Guid.NewGuid(),
                    EventType = "A", // Added
                    TableName = tableName,
                    RecordID = dbEntry.CurrentValues.GetValue<object>(keyName).ToString(),  // Again, adjust this if you have a multi-column key
                    ColumnName = "*ALL",    // Or make it nullable, whatever you want
                    NewValue = (dbEntry.CurrentValues.ToObject() is IDescribableEntity) ? (dbEntry.CurrentValues.ToObject() as IDescribableEntity).Describe() : dbEntry.CurrentValues.ToObject().ToString(),
                    Created_by = userId,
                    Created_date = changeTime
                }
                    );
            }
            else if (dbEntry.State == EntityState.Deleted)
            {
                // Same with deletes, do the whole record, and use either the description from Describe() or ToString()
                result.Add(new Log()
                {
                    LogID = Guid.NewGuid(),
                    EventType = "D", // Deleted
                    TableName = tableName,
                    RecordID = dbEntry.OriginalValues.GetValue<object>(keyName).ToString(),
                    ColumnName = "*ALL",
                    NewValue = (dbEntry.OriginalValues.ToObject() is IDescribableEntity) ? (dbEntry.OriginalValues.ToObject() as IDescribableEntity).Describe() : dbEntry.OriginalValues.ToObject().ToString(),
                    Created_by = userId,
                    Created_date = changeTime
                }
                    );
            }
            else if (dbEntry.State == EntityState.Modified)
            {
                foreach (string propertyName in dbEntry.OriginalValues.PropertyNames)
                {
                    // For updates, we only want to capture the columns that actually changed
                    if (!object.Equals(dbEntry.OriginalValues.GetValue<object>(propertyName), dbEntry.CurrentValues.GetValue<object>(propertyName)))
                    {
                        result.Add(new Log()
                        {
                            LogID = Guid.NewGuid(),
                            EventType = "M",    // Modified
                            TableName = tableName,
                            RecordID = dbEntry.OriginalValues.GetValue<object>(keyName).ToString(),
                            ColumnName = propertyName,
                            OriginalValue = dbEntry.OriginalValues.GetValue<object>(propertyName) == null ? null : dbEntry.OriginalValues.GetValue<object>(propertyName).ToString(),
                            NewValue = dbEntry.CurrentValues.GetValue<object>(propertyName) == null ? null : dbEntry.CurrentValues.GetValue<object>(propertyName).ToString(),
                            Created_by = userId,
                            Created_date = changeTime
                        }
                            );
                    }
                }
            }
            // Otherwise, don't do anything, we don't care about Unchanged or Detached entities

            return result;
        }

        public DbSet<Log> Log { get; set; }

そして、ここにログクラスがあります

[Table("N_Log")]
public class Log
{
    [Key]
    public Guid LogID { get; set; }

    [Required]
    public string EventType { get; set; }

    [Required]
    public string TableName { get; set; }

    public string ActionID { get; set; }

    [Required]
    public string RecordID { get; set; }

    [Required]
    public string ColumnName { get; set; }

    public string OriginalValue { get; set; }

    public string NewValue { get; set; }

    [Required]
    public string Created_by { get; set; }

    [Required]
    public DateTime Created_date { get; set; }
}
于 2014-07-16T07:33:21.823 に答える