我有一个MSSQL数据库和一个带有EntityFramework Core的ASP.NET MVC Core WebApi项目。
我有自定义表名为Users和BlogPosts。 我想每次从Users表中更新Id时更新BlogPosts列“ModifiedById”。
我考虑使用SQL Trigger进行此类操作,但我无法找到一种方法来为每个查询传递用户ID。缺点是每个表需要一个触发器。
有更好的解决方案吗?
[edit]是的,有:)正如所提出的,最好的选择是覆盖DbContext的SaveChanges()方法。
的问候, 第
答案 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,
}