【发布时间】:2013-12-09 18:56:30
【问题描述】:
我有一个经典的 3 层项目,它有这些层:
- UI(WinForm 项目)
- BLL
- DAL(使用 EF 代码优先)
我的实体已断开连接POCOs,我使用它们在层之间传递数据并使用它们绑定到 UI 控件。
我将一些相关实体的图表加载到 UI(例如Order,每个OrderLines 和Product OrderLine),用户可以添加一些新实体,编辑一些其他实体并删除一些其他实体在此图中,然后将此图发送到 DAL 以将此更改持久保存到 DB。
我想将所有这些 CRUD 操作应用到一个 transaction 中。因此,对于这个要求,并且因为我的POCOs 已断开连接,我使用以下State enum 为我的BaseEntity 类保持其状态在客户端(所有其他实体继承自BaseEntity):
public enum States
{
Unchanged,
Added,
Modified,
Deleted
}
在 DAL 中,当我想保留这个更改的对象图时,因为这个实体图与 DbContext 断开连接,我应该将我的图的根附加到创建的 DbContext 并且因为在将根附加到所有 DbContext 状态之后DbContext 中的条目将是 Added,我应该将 DbContext 中每个 Entry 的 State 与图表中的实体 State 同步,所以我使用这些方法来执行此操作:
public static EntityState ConvertState(BaseEntity.States state)
{
switch (state)
{
case BaseEntity.States.Added:
return EntityState.Added;
case BaseEntity.States.Modified:
return EntityState.Modified;
case BaseEntity.States.Deleted:
return EntityState.Deleted;
default:
return EntityState.Unchanged;
}
}
public void ApplyChanges<TEntity>(TEntity root) where TEntity : BaseEntity
{
_dbContext.Set<TEntity>().Add(root);
foreach (var entry in _dbContext.ChangeTracker
.Entries<BaseEntity>())
{
BaseEntity stateInfo = entry.Entity;
entry.State = ConvertState(stateInfo.State);
}
}
如您所见,我在 EF 之外做了很多事情并且不使用 EF 功能,因为我的 POCO 已断开连接。
有什么方法可以应用这些批量 CRUD 方案,而无需断开我的 POCOs 与 DbContext 的连接?
【问题讨论】:
-
为什么不使用经典实体、视图模型和像 automapper 这样的映射器来进行翻译?然后,您将获得像 EF 这样的 ORM 的所有功能。你在这里有点重新发明轮子,我不清楚为什么。
-
@Maess 是对的,如果您使用视图模型,您将能够将所有更改应用到上下文并一次保存。然后所有状态将由上下文自动处理。您的另一个选择是在您的 UI 中创建和使用上下文,但这会产生非常强烈的代码气味。
-
@Maess : 我可以用这种方法应用这个场景吗?
-
您可以使用它来确定实体的上下文状态,是的。但如果你使用 Onion 架构,调用适当的存储库方法会将其抽象掉。
-
@Maess : 这个方法有什么好的样本吗?
标签: c# entity-framework poco crud dbcontext