DateCreated或Modified Column - 实体框架或在SQL Server上使用触发器

anI*_*Mer 12 sql-server triggers entity-framework

在我阅读附加链接中的一个问题之后,我了解了如何在Entity Framework中设置DateCreated和DateModified列并在我的应用程序中使用它.但是,在旧的SQL方式中,触发方式更受欢迎,因为从DBA的角度来看更安全.

那么关于哪种方式的建议是最佳做法?应该在实体框架中为应用程序完整性而设置吗?或者应该使用触发器,因为从数据安全的角度来看它更有意义吗?或者有没有办法在实体框架中组合触发器?谢谢.

EF CodeFirst:Rails风格的创建和修改列

顺便说一下,即使它并不重要,我正在使用ASP.NET MVC C#构建这个应用程序.

Tim*_*ers 23

意见:触发器就像隐藏的行为,除非你去寻找它们,否则你通常不会意识到它们在那里.我也喜欢在使用EF时尽可能保持DB"哑",因为我使用的是EF,所以我的团队不需要维护SQL代码.

对于我的解决方案(在另一个同时包含DataContext的项目中,将ASP.NET WebForms和MVC与业务逻辑混合在一起):

我最近有一个类似的问题,虽然对于我的情况它更复杂(DatabaseFirst,所以需要一个自定义的TT文件),解决方案大致是相同的.

我创建了一个界面:

public interface ITrackableEntity
{
    DateTime CreatedDateTime { get; set; }
    int CreatedUserID { get; set; }
    DateTime ModifiedDateTime { get; set; }
    int ModifiedUserID { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后我就在我需要的任何实体上实现了该接口(因为我的解决方案是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)));
}
Run Code Online (Sandbox Code Playgroud)

唯一剩下的就是将以下内容添加到我的部分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();
    }
Run Code Online (Sandbox Code Playgroud)

请注意,每次创建DataContext类时,我都会将当前用户ID保存在私有字段中.


mar*_*c_s 6

至于DateCreated,我只想在该列集上添加一个默认约束,以便SYSDATETIME()在向表中插入新行时生效.

DateModified个人而言,我可能会在这些表上使用触发器.

在我看来,触发方法:

  • 让它更容易; 每次我保存一个实体来设置它时,我都不必担心并记住DateModified

  • 使它"更安全",因为DateModified如果有人在我的应用程序中找到一种方法直接修改数据库中的数据(使用例如Access或Excel或其他东西),它也会应用.