【问题标题】:How can I add default values to a property when saving using Code First EF4.1?使用 Code First EF4.1 保存时如何向属性添加默认值?
【发布时间】:2011-03-31 13:16:14
【问题描述】:

我首先创建了一些这样的模型:

public abstract class EditableBase
{
    public DateTime CreatedOn { get; set; }
    public DateTime ModifiedOn { get; set; }

    public int CreatedBy { get; set; }
    public int ModifiedBy { get; set; }
}

public class Project : EditableBase
{
    public int ProjectId { get; set; }
    public string ProjectName { get; set; }
}

我在应用启动时使用这一行:

Database.SetInitializer<ModelContext>(
            new DropCreateDatabaseIfModelChanges<ModelContext>());

创建了一个名为 Projects 的表,其中包含上述所有属性作为列...这正是我想要的。

但是,现在我需要在 DbContext 上发出 SaveChanges() 时填充一些默认值。保存时,我需要使用适当的值更新 ModifiedOn 和 ModifiedBy 属性。

通常我至少会在数据库端(触发器或存储过程)执行 DateTime 值,但这显然不是一个选项,因为数据库将在类更改时被删除。而且由于我首先编写代码,因此我没有可以调整属性的模型设计器。

我想做的是在 EditableBase 类中添加一个方法,该方法在执行 SaveChanges() 时被调用,从而将所有涉及的逻辑保存在一个地方。是否有可能做到这一点?实现我的目标的最佳方式是什么?

【问题讨论】:

  • 不错的命名约定!我想不出从日期字段的名称中获取数据类型(日期)的方法。

标签: c# entity-framework entity-framework-4.1


【解决方案1】:

在派生的DbContext 中覆盖SaveChanges

public override int SaveChanges()
{
    foreach(var entry in ChangeTracker.Entries<EditableBase>())
    {
        var entity = entry.Entity;
        if (entry.State == EntityState.Added)
        {
            entity.CreatedOn = ...;
            entity.CreatedBy = ...;
        }
        else if (entry.State == EntityState.Modified)
        {
            entity.ModifiedOn = ...;
            entity.ModifiedBy = ...;
        }
    }

    return base.SaveChanges();
}

我只是不确定泛型 Entries 是否会直接与您的基本类型一起使用,因为它实际上并未映射为基本实体。还有非通用版本,因此您可以将其重写为更复杂的 linq 查询或循环测试每个条目的实体类型。

【讨论】:

  • 这似乎是最正确的答案。我对此并不感到兴奋,因为它看起来有点矫枉过正,但我​​没有看到任何其他选择。
  • 我仅将它用于 DateCreated。但是当我进行编辑时,这个值会被覆盖并设置为 null 或空字符串
  • 如果使用自动属性,会不会有同样的效果?:public DateTime ModifiedOn { get; set; } = Datetime.Now;
【解决方案2】:

好吧,您可以完全控制实体的代码。我想您可能希望实现类似 IPropertyChanged 的​​模式来更新您的属性。

【讨论】:

  • 你能扩展这个答案吗?我知道我可以完全控制我的实体,但我不知道我可以完全控制 DbContext 中的 SaveChanges() 方法。我需要的钩子在哪里?
  • 我只是指出您可以在您的实体上实现 IPropertyChanged(类似于 WPF); aka,当属性更改时,您自己更新 ModifiedOn 属性,而不是在 SaveChanges 中。
  • 我明白你现在的意思了。这似乎需要做很多工作。例如,如果我有十几个模型都继承自 EditBase,并且每个模型都有 20 或 30 个属性,那么我必须添加大量代码,以便在继承 EditBase 并调用 SaveChanges()。
【解决方案3】:

是否考虑了this post 中的两个选项,您在设置器(或构造器)上做了什么?

默认属性解决方案似乎不错。

【讨论】:

  • 嗯,这个解决方案部分有效,它最终是我选择做的。它虽然有点笨重。当保存的值加载并覆盖构造函数放入的任何内容时,它不起作用。ModifiedBy 就是一个很好的例子。我真的只想在保存时设置它。
猜你喜欢
  • 2013-05-21
  • 2015-08-21
  • 1970-01-01
  • 2013-11-02
  • 2011-09-06
  • 1970-01-01
  • 1970-01-01
  • 2016-05-11
相关资源
最近更新 更多