我的核心项目是C#。
我在一个数据库上工作,其中一些表有“user_mod”和“date_mod”列用于签名谁和什么时候做了一些mods和“data_new”和“user_new”相同。
我的问题:有没有办法集中这个并自动插入这些数据,我在哪里创建dbContext
的实例?
如果没有,我将使用审计跟踪工具。我已经看到其中的一些,但是有一个问题:所有这些,在我的模型中需要一些代码。但是我不想在我的模型中写,因为如果我必须改变它,我将失去mod。是否可以在不写入模型文件的情况下使用EF6的审计跟踪?怎么样?
编辑:
我尝试覆盖saveChanges。
public partial class PieEntities : DbContext
{
public override int SaveChanges(System.Data.Objects.SaveOptions options)
{
var timestamp = DateTime.Now;
EntityState es = EntityState.Added;
ObjectStateManager o = new ObjectStateManager();
foreach (ObjectStateEntry entry in o.GetObjectStateEntries(EntityState.Added )) {
if (entry.Entity.GetType() == typeof(TabImpianti)) {
TabImpianti impianto = entry.Entity as TabImpianti;
impianto.DATA_INS = timestamp;
impianto.DATA_MOD = timestamp;
string u = mdlImpostazioni.p.UserName;
impianto.USER_INS = u;
impianto.USER_MOD = u;
}
}
return base.SaveChanges(options);
}
}
更新:我总结了solution here。
答案 0 :(得分:69)
如果使用EF6' DbContext
,您可以在ChangeTracker
覆盖中使用SaveChanges
来查找自定义类型的添加/修改实体,例如IAuditedEntity。
public interface IAuditedEntity {
string CreatedBy { get; set; }
DateTime CreatedAt { get; set; }
string LastModifiedBy { get; set; }
DateTime LastModifiedAt { get; set; }
}
public override int SaveChanges() {
var addedAuditedEntities = ChangeTracker.Entries<IAuditedEntity>()
.Where(p => p.State == EntityState.Added)
.Select(p => p.Entity);
var modifiedAuditedEntities = ChangeTracker.Entries<IAuditedEntity>()
.Where(p => p.State == EntityState.Modified)
.Select(p => p.Entity);
var now = DateTime.UtcNow;
foreach (var added in addedAuditedEntities) {
added.CreatedAt = now;
added.LastModifiedAt = now;
}
foreach (var modified in modifiedAuditedEntities) {
modified.LastModifiedAt = now;
}
return base.SaveChanges();
}
答案 1 :(得分:16)
此处有 nuget包 https://www.nuget.org/packages/TrackerEnabledDbContext
来源: https://github.com/bilal-fazlani/tracker-enabled-dbcontext
答案 2 :(得分:5)
有一种方法可以执行此操作:您可以创建与对象上下文同名的分部类,并实现SaveChanges
方法的覆盖。在此覆盖中,您可以查看将推送到数据库并处理它们的所有更改。
您可以按照自己喜欢的方式处理它们,在下面的示例中,我创建了一个包含创建日期和修改日期的接口IAutoTimestampEntity
。任何此类对象都会随着更改时间自动更新。
public override int SaveChanges(System.Data.Objects.SaveOptions options)
{
var timestamp = DateTime.Now;
foreach (var InsertedAutoTimestampEntity in ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Added).Select(ose => ose.Entity).OfType<IAutoTimestampEntity>())
{
InsertedAutoTimestampEntity.CreationDate = timestamp;
InsertedAutoTimestampEntity.ModificationDate = timestamp;
}
foreach (var UpdatedAutoTimestampEntity in ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Modified).Select(ose => ose.Entity).OfType<IAutoTimestampEntity>())
{
UpdatedAutoTimestampEntity.ModificationDate = timestamp;
}
return base.SaveChanges(options);
}
您可以使用相同的原则,或者您可以详细查看每个已更改实体的类型。我喜欢界面的声明方面。它允许您显式地公开自动化的一个方面,而不是让它由EF层静默完成。
如果您有DbContext
而不是ObjectContext
,请将DbContext
投向IObjectContextAdapter
以访问ObjectStateManager
答案 3 :(得分:0)
除了@AlaaMasoud的答案。
使用CreatedDate
和UpdatedDate
:
interface IEntityDate
{
DateTime CreatedDate { get; set; }
DateTime UpdatedDate { get; set; }
}
public abstract class EntityBase<T1>: IEntityDate
{
public T1 Id { get; set; }
public virtual DateTime CreatedDate { get; set; }
public virtual string CreatedBy { get; set; }
public virtual DateTime UpdatedDate { get; set; }
public virtual string UpdatedBy { get; set; }
}
public override int SaveChanges()
{
var now = DateTime.Now;
foreach (var changedEntity in ChangeTracker.Entries())
{
if (changedEntity.Entity is IEntityDate entity)
{
switch (changedEntity.State)
{
case EntityState.Added:
entity.CreatedDate = now;
entity.UpdatedDate = now;
break;
case EntityState.Modified:
Entry(entity).Property(x => x.CreatedDate).IsModified = false;
entity.UpdatedDate = now;
break;
}
}
}
return base.SaveChanges();
}
要处理CreatedBy
和UpdatedBy
,我使用DbContext
的包装器是这样的:
public interface IEntity
{
DateTime CreatedDate { get; set; }
string CreatedBy { get; set; }
DateTime UpdatedDate { get; set; }
string UpdatedBy { get; set; }
}
public interface ICurrentUser
{
string GetUsername();
}
public class ApplicationDbContextUserWrapper
{
public ApplicationDbContext Context;
public ApplicationDbContextUserWrapper(ApplicationDbContext context, ICurrentUser currentUser)
{
context.CurrentUser = currentUser;
this.Context = context;
}
}
public class ApplicationDbContext : DbContext
{
public ICurrentUser CurrentUser;
public override int SaveChanges()
{
var now = DateTime.Now;
foreach (var changedEntity in ChangeTracker.Entries())
{
if (changedEntity.Entity is IEntity entity)
{
switch (changedEntity.State)
{
case EntityState.Added:
entity.CreatedDate = now;
entity.UpdatedDate = now;
entity.CreatedBy = CurrentUser.GetUsername();
entity.UpdatedBy = CurrentUser.GetUsername();
break;
case EntityState.Modified:
Entry(entity).Property(x => x.CreatedBy).IsModified = false;
Entry(entity).Property(x => x.CreatedDate).IsModified = false;
entity.UpdatedDate = now;
entity.UpdatedBy = CurrentUser.GetUsername();
break;
}
}
}
return base.SaveChanges();
}
...
来源: