C# 在DDD中将创建日期和创建人放在何处?
我使用实体框架,希望使用DDD原则。但是,有一些关于实体的信息,这些实体处于什么是日志/持久性信息和什么是关于域对象的信息之间的边界 在我的情况下,这些被放在一个抽象基类中,所有实体都从该基类继承:C# 在DDD中将创建日期和创建人放在何处?,c#,entity-framework,design-patterns,ef-code-first,domain-driven-design,C#,Entity Framework,Design Patterns,Ef Code First,Domain Driven Design,我使用实体框架,希望使用DDD原则。但是,有一些关于实体的信息,这些实体处于什么是日志/持久性信息和什么是关于域对象的信息之间的边界 在我的情况下,这些被放在一个抽象基类中,所有实体都从该基类继承: public abstract class BaseEntity: IBaseEntity { /// <summary> /// The unique identifier /// </summary> public int Id { g
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;
}
}
公共抽象类BaseEntity:IBaseEntity
{
///
///唯一标识符
///
公共int Id{get;set;}
///
///创建此实例的用户
///
公共用户CreatedBy{get;set;}
///
///创建对象的日期和时间
///
公共日期时间CreatedDate{get;set;}
///
///哪个用户是最后一个更改此对象的用户
///
公共用户LastChangedBy{get;set;}
///
///上次更改对象是什么时候
///
公共日期时间LastChangedDate{get;set;}
///
///这是实体的状态。有关详细信息,请参阅EntityStatus文档。
///
公共EntityStatus EntityStatus{get;set;}
///
///设置新对象的默认值
///
受保护的BaseEntity()
{
CreatedDate=DateTime.Now;
EntityStatus=EntityStatus.Active;
LastChangedDate=DateTime.Now;
}
}
现在,如果不提供日期和时间,就无法实例化域对象。然而,我觉得这是一个错误的地方把它。我真的可以为两者辩护。也许它根本不应该与域混合在一起
因为我首先使用EF代码,所以将其放在那里是有意义的,否则我还需要创建从DAL中的基类继承的新类,复制代码并需要映射到域对象和MVC模型,这看起来比上述方法更混乱
问题:
在域模型中使用DateTime.Now可以吗?您首先使用DDD和EF代码将此类信息放在哪里?应该在域对象中设置用户,还是在业务层中需要用户
更新
我认为jgauffin在这里是正确的答案——但这确实是一个相当根本的变化。然而,在我寻找另一个解决方案时,我几乎用这个解决了它。我使用ChangeTracker.Entries查找是否添加或修改了实体,并相应地设置字段。这是在我的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();
}
public void SaveChanges(用户已更改)
{
foreach(在_context.ChangeTracker.Entries()中的var条目)
{
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.Now可以吗
这并不可怕,但问题是,您最终将不得不复制代码,而且实现一致性将更加困难
您首先使用DDD和EF代码将此类信息放在哪里
您断言此类信息不属于您的域是正确的。它通常被称为审核日志或跟踪。有几种方法可以使用EF实现审核。例如,请看一看,或者只是四处搜索EF审核实现。其思想是,在EF持续更改实体之前,它会引发一个事件您可以侦听并分配所需的审核值
应该在域对象中设置用户,还是在
业务层
最好在基础设施/存储库级别通过上述审计实现来处理此问题。这是数据持久化之前的最后一站,因此是处理此问题的最佳场所
在域模型中使用DateTime.Now可以吗
对
您首先使用DDD和EF代码将此类信息放在何处?用户应该在域对象中设置还是在业务层中要求设置
首先,DDD模型总是处于有效状态。这对于公共setter是不可能的。在DDD中,您使用方法处理模型,因为这些方法可以确保所有必需的信息都已指定且有效
例如,如果您可以将一个项目标记为已完成,则很可能更新日期也应该更改。如果您让调用代码确保该日期,则很可能会将其遗忘在某个地方。相反,您应该具有以下内容:
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;
}
}
阅读我关于这种方法的博客帖子:
更新
如何让舒尔在以后更改“CreatedBy”和“CreatedDate”
对于模型,我通常有两个构造函数,它们也适合DB。一个受保护的构造函数可供我的持久性层使用,另一个需要必填字段。将createdby放在该构造函数中,并在其中设置createdate:
public class YourModel
{
public YourModel(User createdBy)
{
CreatedDate = DateTime.Now;
CreatedBy = createdby;
}
// for persistance
protected YourModel()
{}
}
然后为这些字段设置私有setter
我收到很多关于“构造函数中的虚拟成员调用”的警告,我以前读过这方面的内容,但这并不是一个好的实践
这通常不是问题。请阅读此处:我以前没有听说过,但它看起来是一个非常好的解决方案。我必须更仔细地研究它。您知道这是否会导致实体框架的新版本出现问题吗