将创建日期和由DDD中创建的位置



我使用实体框架并想要使用DDD原理。但是,有一些有关实体在登录/持久性信息与域对象的信息之间的边界上的信息。

i我的情况将所有实体都从以下基础上继承的抽象基类放在:

 public abstract class BaseEntity: IBaseEntity
{
    /// <summary>
    /// The unique identifier
    /// </summary>
    public int Id { get; set; }
    /// <summary>
    /// The user that created this instance
    /// </summary>
    public User CreatedBy { get; set; }
    /// <summary>
    /// The date and time the object was created
    /// </summary>
    public DateTime CreatedDate { get; set; }
    /// <summary>
    /// Which user was the last one to change this object
    /// </summary>
    public User LastChangedBy { get; set; }
    /// <summary>
    /// When was the object last changed
    /// </summary>
    public DateTime LastChangedDate { get; set; }
    /// <summary>
    /// This is the status of the entity. See EntityStatus documentation for more information.
    /// </summary>
    public EntityStatus EntityStatus { get; set; }
    /// <summary>
    /// Sets the default value for a new object
    /// </summary>
    protected BaseEntity()
    {
        CreatedDate = DateTime.Now;
        EntityStatus = EntityStatus.Active;
        LastChangedDate = DateTime.Now;
    }
}

现在,如果不提供日期和时间,就无法实例化域对象。但是,我觉得这是错误的地方。我真的可以为两者争论。也许根本不应该与域混合?

由于我首先使用EF代码,因此将其放在那里是有意义的,否则我需要创建从dal中的基类继承的新类,重复代码,并需要映射到两个域对象和MVC模型似乎比上面的方法更混乱。

问题:

可以在域模型中使用dateTime.now吗?您在哪里使用DDD和EF代码将这种信息放在哪里?应该在域对象中设置用户或在业务层中需要它吗?

update

我认为jgauffin har在这里正确答案 - 但这确实是一个根本的变化。但是,在搜索替代解决方案时,我几乎对此解决了它。我使用changetracker.entries查找UT,如果添加或修改了实体,并相应地设置了字段。这是在我的unitofwork save()方法中完成的。

问题是加载导航属性,例如用户(DateTime设置正确)。可能是因为用户是实体继承的抽象基类属性。我也不喜欢将字符串放在其中,但是它可能会为某人解决一些简单的方案,因此我在此处发布解决方案:

        public void SaveChanges(User changedBy)
    {
        foreach (var entry in _context.ChangeTracker.Entries<BaseEntity>())
        {
            if (entry.State == EntityState.Added)
            {
                entry.Entity.CreatedDate = DateTime.Now;
                entry.Entity.LastChangedDate = DateTime.Now;
                entry.Entity.CreatedBy = changedBy;
                entry.Entity.LastChangedBy = changedBy;
            }
            if (entry.State == EntityState.Modified)
            {
                entry.Entity.CreatedDate = entry.OriginalValues.GetValue<DateTime("CreatedDate");
                entry.Entity.CreatedBy = entry.OriginalValues.GetValue<User>("CreatedBy");
                entry.Entity.LastChangedDate = DateTime.Now;
                entry.Entity.LastChangedBy = changedBy;
            }
        }

        _context.SaveChanges();
    }

可以在域模型中使用dateTime.now吗?

是。

您在哪里使用DDD和EF代码将这种信息放在哪里?应该在域对象中设置用户或在业务层中需要它吗?

很好。首先:DDD模型始终处于有效状态。公共设定者是不可能的。在DDD中,您可以使用方法使用模型,因为这些方法可以确保已指定所有必需的信息并有效。

例如,如果您可以将项目标记为已完成的项目,则可能也应更改UpdatedAt日期。如果让通话代码确保可能会忘记某个地方。相反,您应该有类似的东西:

public class MyDomainModel
{
    public void MarkAsCompleted(User completedBy)
    {
        if (completedBy == null) throw new ArgumentNullException("completedBy");
        State = MyState.Completed;
        UpdatedAt = DateTime.Now;
        CompletedAt = DateTime.Now;
        CompletedBy = completedBy;
    }
}

阅读我的博客文章:http://blog.gauffin.org/2012/06/protect-your-data/

update

如何制作shure,以后

上没有更改"创建"one_answers" createDate"

我通常有两个构造函数,适合DB。一个受保护的一个可以由我的持久性层使用,一个需要强制性字段。将创建者放入该构造函数中,并在其中设置创建物:

public class YourModel
{
    public YourModel(User createdBy)
    {
        CreatedDate = DateTime.Now;
        CreatedBy = createdby;
    }
    // for persistance
    protected YourModel()
    {}
}

然后有这些字段的私人设置。

我得到了很多r#警告"构造中的虚拟会员呼叫",我以前读过它,这不是一个好习惯。

这通常不是问题。在此处阅读:构造函数中的虚拟会员

可以在域模型中使用dateTime.now吗?

这并不可怕,但是问题是您最终将不得不重复代码,并且更难实现一致性。

首先使用DDD和EF代码放在哪里?

您是正确的,可以断言此类信息不属于您的域中。通常称为审核日志或步道。有几种使用EF实施审核的方法。看一下审核dbContext-例如,实体框架审核上下文,或者只是搜索EF审核实现。这个想法是,在EF持续变化为实体之前,它提出了一个事件,您可以收听并分配所需的审核值。

应该在域对象中设置用户或在 业务层?

最好在基础架构/存储库级别上使用上述审核实现。这是数据持续存在之前的最后一站,因此是照顾这个问题的理想场所。

最新更新