意见:触发器就像隐藏的行为,除非你去寻找它们,否则你通常不会意识到它们就在那里。我还希望在使用 EF 时尽可能保持数据库“哑”,因为我使用的是 EF,所以我的团队不需要维护 SQL 代码。
对于我的解决方案(在 C# 中将 ASP.NET WebForms 和 MVC 与另一个项目中的业务逻辑混合,该项目也包含 DataContext):
我最近遇到了类似的问题,虽然对于我的情况来说它更复杂(DatabaseFirst,因此需要一个自定义 TT 文件),但解决方案基本相同。
我创建了一个界面:
public interface ITrackableEntity
{
DateTime CreatedDateTime { get; set; }
int CreatedUserID { get; set; }
DateTime ModifiedDateTime { get; set; }
int ModifiedUserID { get; set; }
}
然后我只是在我需要的任何实体上实现了该接口(因为我的解决方案是 DatabaseFirst,我更新了 TT 文件以检查表是否有这四列,如果有,则将接口添加到输出中)。
更新:这是我对 TT 文件的更改,我在其中更新了EntityClassOpening()
方法:
public string EntityClassOpening(EntityType entity)
{
var trackableEntityPropNames = new string[] { "CreatedUserID", "CreatedDateTime", "ModifiedUserID", "ModifiedDateTime" };
var propNames = entity.Properties.Select(p => p.Name);
var isTrackable = trackableEntityPropNames.All(s => propNames.Contains(s));
var inherits = new List<string>();
if (!String.IsNullOrEmpty(_typeMapper.GetTypeName(entity.BaseType)))
{
inherits.Add(_typeMapper.GetTypeName(entity.BaseType));
}
if (isTrackable)
{
inherits.Add("ITrackableEntity");
}
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}partial class {2}{3}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
_code.Escape(entity),
_code.StringBefore(" : ", String.Join(", ", inherits)));
}
剩下的唯一事情是将以下内容添加到我的部分 DataContext 类中:
public override int SaveChanges()
{
// fix trackable entities
var trackables = ChangeTracker.Entries<ITrackableEntity>();
if (trackables != null)
{
// added
foreach (var item in trackables.Where(t => t.State == EntityState.Added))
{
item.Entity.CreatedDateTime = System.DateTime.Now;
item.Entity.CreatedUserID = _userID;
item.Entity.ModifiedDateTime = System.DateTime.Now;
item.Entity.ModifiedUserID = _userID;
}
// modified
foreach (var item in trackables.Where(t => t.State == EntityState.Modified))
{
item.Entity.ModifiedDateTime = System.DateTime.Now;
item.Entity.ModifiedUserID = _userID;
}
}
return base.SaveChanges();
}
请注意,每次创建时,我都将当前用户 ID 保存在 DataContext 类的私有字段中。