EntityFramework将执行查询的用户传递给MSSQL

时间:2016-11-14 10:52:02

标签: c# asp.net sql-server entity-framework

我有一个MSSQL数据库和一个带有EntityFramework Core的ASP.NET MVC Core WebApi项目。

我有自定义表名为Users和BlogPosts。 我想每次从Users表中更新Id时更新BlogPosts列“ModifiedById”。

我考虑使用SQL Trigger进行此类操作,但我无法找到一种方法来为每个查询传递用户ID。缺点是每个表需要一个触发器。

有更好的解决方案吗?

[edit]是的,有:)正如所提出的,最好的选择是覆盖DbContext的SaveChanges()方法。

的问候, 第

3 个答案:

答案 0 :(得分:2)

我通常通过继承和覆盖SaveChanges()来实现它 - 这与Code First一起使用,并且节省了必须手动将审计字段添加到每个类。

public abstract class TrackedEntity
{
    public DateTime CreatedDate { get; set; }
    public DateTime ModifiedDate { get; set; }
    public string ModifiedBy { get; set; }
}


public class SomeOtherClass : TrackedEntity
{
     // Class specific properties here
}

然后在你的DbContext

private User _loggedOnUser

    public override int SaveChanges()
    {
        var timestamp = DateTime.Now;

        // First look at new items these need created date adding
        var addedEntities = ChangeTracker.Entries().Where(x => x.State == EntityState.Added).Select(x => x.Entity);

        foreach (var addition in addedEntities)
        {
            var entity = addition as TrackedEntity;

            if (entity != null)
            {
                entity.CreatedDate = timestamp;
                entity.ModifiedDate = timestamp;
                entity.ModifiedBy = _loggedOnUser;
            }
        }

        // Next look at modified entries
        var modifiedEntities = ChangeTracker.Entries().Where(x => x.State == EntityState.Modified || x.State == EntityState.Deleted);

        foreach (var update in modifiedEntities)
        {
            // Only check tracked entities if modified
            if (update.State == EntityState.Modified)
            {
                var tracked = update.Entity as TrackedEntity;

                if (tracked != null)
                {
                    tracked.ModifiedDate = timestamp;
                    tracked.ModifiedBy = _loggedOnUser;
                }
            }
        }
   }

并获取用户

    private void GetUser()
    {

        string user = string.Empty;

        // if we have an http context, lets try it first
        if (System.Web.HttpContext.Current != null)
        {
            if (System.Web.HttpContext.Current.User.Identity != null && System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
                user = System.Web.HttpContext.Current.User.Identity.Name;
        }

        if (user == null)
            user = System.Threading.Thread.CurrentPrincipal.Identity.Name;

        _loggedOnUser = this.Users.SingleOrDefault(x => x.Username == user);
    }

答案 1 :(得分:1)

谢谢@Igor和@ ste-fu。

根据建议,我已按以下方式覆盖SaveChanges:

    public override int SaveChanges()
    {
        var timeStamp = DateTime.UtcNow;
        var userId = this.GetAuthenticatedUser();

        this.HandleAddedEntities(userId, timeStamp);
        this.HandleModifiedEntities(userId, timeStamp);

        return base.SaveChanges();
    }
    private void HandleAddedEntities(Guid userId, DateTime timeStamp)
    {
        var entities = ChangeTracker.Entries()
                        .Where(x => x.Entity is IAddedEntity && 
                                    x.State == EntityState.Added)
                        .Select(x => x.Entity as IAddedEntity);

        foreach (var e in entities)
        {
            e.CreatedById = userId;
            e.CreatedOn = timeStamp;
        }
    }

    private void HandleModifiedEntities(Guid userId, DateTime timeStamp)
    {
        var entities = ChangeTracker.Entries()
                         .Where(x => x.Entity is IModifiedEntity && 
                                     (x.State == EntityState.Added || 
                                      x.State == EntityState.Modified))
                         .Select(x => x.Entity as IModifiedEntity);

        foreach (var e in entities)
        {
            e.ModifiedById = userId;
            e.ModifiedOn = timeStamp;
        }
    }

正如评论中所提到的,我使用了接口,因为这样我对其他"泛型触发器开放了#34;如果需要的话。

感谢大家的快速反应。

答案 2 :(得分:0)

如果您正在使用WebMatrix:

using WebMatrix.WebData;
//...
BlogPost bp = new BlogPost()
{
    // other properties
    ModifiedById = WebSecurity.CurrentUserId,
}