Вставки журнала аудита - PullRequest
1 голос
/ 30 июня 2011

Мне было интересно, может ли кто-нибудь предложить какой-нибудь вклад для реализации ведения журнала аудита для вставок.Мне нужно убедиться, что это транзакция.

У меня есть аудит DbSet, построенный на следующем POCO:

public class Audit {
    public int Id { get; set; }
    public User User { get; set; }
    public DateTime Created { get; set; }
    public string Type { get; set; }
    public int EntityId { get; set; }
    public string Message { get; set; }
}

У меня есть DbSet, скажем Users, что когда я делаю вставку, яхотите создать автоматически добавляемую сущность Audit в Audit DbSet.Рассмотрим следующий код:

//var user = new User();
//user.Created = DateTime.Now;
//user.Username = "testuser";
//user.Password = "testpassword";
//dataContext.Users.Add(user);

var post = new Post();
post.Created = DateTime.Now;
post.Title = "A sample post";
post.Published = true;
post.Body = "Some content goes in here...";

dataContext.Posts.Add(post);

var audit = new Audit();
audit.Created = DateTime.Now;
audit.User = CurrentUser.User; // Currently logged in user
audit.Type = "Post.Add";
audit.EntityId = post.Id;
audit.Message = "New post was created";

dataContext.Audits.Add(audit);

dataContext.SaveChanges();

В этом случае объект аудита будет добавлен, но для свойства «EntityId» будет установлено значение 0 (значение по умолчанию), а не идентификатор созданного user post, то есть значение идентификатора (SCOPE_IDENTITY () / @@ IDENTITY).

Я бы хотел сохранить обе точки в одной транзакции, а не разбивать элементы на две транзакции, т.е. сохранять Пользователь Сначала опубликуйте, а затем сохраните Аудит во втором, так как есть вероятность, что Аудит может завершиться неудачей.

Ответы [ 2 ]

2 голосов
/ 03 августа 2011

Переопределите DbContext.SaveChanges () и посмотрите на все ChangeTracker.Entries (). Где (e => e.State! = EntityState.Unchanged).

Вот пример из моего научно-исследовательского проекта:

public override int SaveChanges()
{
    int recordsUpdated = 0;

    var journalEntries = new List<AuditJournal>();

    foreach (var entry in this.ChangeTracker.Entries<ITrackedEntity>().Where(e=>e.State != EntityState.Unchanged))
    {
        AuditJournal journal = new AuditJournal();
        journal.Id = Guid.NewGuid();
        journal.EntityId = entry.Entity.Id.Value;
        journal.EntityType = entry.Entity.EntityType;
        journal.ActionType = entry.State.ToString();
        journal.OccurredOn = DateTime.UtcNow;
        //journal.UserId = CURRENT USER
        //journal.PreviousEntityData = XML SERIALIZATION OF ORIGINAL ENTITTY

        journalEntries.Add(journal);
    }

    using (var scope = new TransactionScope())
    {
        recordsUpdated = base.SaveChanges();

        foreach (var journalEntry in journalEntries)
            this.AuditJournal.Add(journalEntry);

        base.SaveChanges(); //Save journal entries

        scope.Complete();
    }

    return recordsUpdated;
}

//Every entity that needs to be audited has to implement this interface
public interface ITrackedEntity
{
    string EntityType { get; }
    Guid? Id { get; set; }
}
0 голосов
/ 30 июня 2011

Если вы не против добавить пустую ссылку на Post в свою таблицу аудита, вы можете позволить EF сделать всю работу за вас.Удалите свойство EntityId и добавьте в Audit:

public Post Post {get; set;}

А когда вы записываете событие:

audit.Post = Post;

EF вставит сообщение, захватит его ID и добавит ссылку на Audit дляВы в той же транзакции.Мы делаем это точно в нашей собственной модели AuditEvent, у нас есть несколько пустых ссылок на наши различные типы, поэтому с любым данным событием мы можем ссылаться на связанный объект или объекты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...