Breeze.js混合DTO和实体

4
在Ward的文章“The Breeze Server: Have It Your Way”中提到:
典型的业务应用程序至少有200种域模型类型。90%以上的时间,我发送到服务器端的数据形状与我的业务模型实体的形状相同。 …… 当客户端实体的形状与服务器端业务实体的形状不太匹配时,我可能会为该特定情况切换到DTO。
对于我们的应用程序来说,这正是问题的关键所在,但如何才能最好地仅切换一些实体以用于DTO?
例如,我们的用户实体包含不应向客户端公开的敏感属性。它还具有从其他系统拉取并返回给客户端的相关数据,这些数据理想情况下应该只是客户端用户对象上的额外属性。用户似乎是切换到DTO的理想候选人。
如果用户是一个孤立的实体,那么这可能更容易,但问题在于用户基本上随处可见于模型中。例如,几乎每个实体都有一个CreatedBy属性。
是否有一种方法可以在整个模型中将用户实体切换为用户DTO?对于模型中引用用户的所有其他实体,我们仍然需要能够加载它们并展开其用户属性,以查询它们的用户属性,并将更改保存到这些用户属性中。
我不确定如何做这件事,除了构建一个与实体模型95%相同的大型DTO模型,并具有一些映射代码/框架来在它们之间进行转换。但是,正如Ward在这篇文章中所说:“我不喜欢每种类型都使用DTO;那是过度杀伤力的,会破坏生产力。”

我对混合DTO和实体很感兴趣。你有这种情况的工作示例吗?特别是,你如何将DTO添加到元数据中? - Sam
1个回答

5
您身处良好的公司。类似这样的问题正在积累。我希望能够“尽快”提供更好的指导。
短期内(假设您是.NET开发人员),您可以在DocCode示例中找到一些线索。搜索“ProductDto”。DocCode没有展示如何保存对其所做的更改,因此我将推迟到另一个时间。
您的情况实际上可能很容易解决。
步骤1:使用自定义的DbContext
首先编写业务模型的DbContext子类。在这个子类中添加一个对OnModelCreating的重写并教它忽略不应该成为模型一部分的User属性。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
   modelBuilder.Entity<User>().Ignore(u => u.whatever);
   ...
   base.OnModelCreating(modelBuilder);
}

现在使用这个派生的 DbContext 来与客户端通信。
请注意,这只涉及非常少量的代码,并且易于维护。它不会干扰您对基本 DbContext 的使用,后者仍然可以完全访问所有 User 的属性。
第二步:配置 JSON.NET 以排除这些属性的序列化
请按照 James Newton King 的指导 进行操作。特别是要看 IContractResolver,如果您不想用 [JsonIgnore] 属性装饰 / 污染您的 User 类。James 是 JSON.NET 的作者。

2
保存更改是有趣的部分,因此“更好的指导”将非常有帮助! - pawel
3
确实! :-). 简言之:(1)从 EntityInfos 中删除DTO,(2)从数据库中检索相应的业务模型实体(如果这是插入,则创建此类实体),(3)使用DTO更新此副本,(4)将此实体添加到 EntityInfos(不要忘记为更新添加 OriginalValues 属性),(5)对所有这样的DTO重复此过程,(6)完成后由EF保存它,(7)拦截“保存后”事件,并将已更新/插入的业务实体重新映射回其DTO形式,以便将DTO发送回客户端,而不是“真实”实体。细节中隐藏着问题。 - Ward
1
@Ward - 这个方法适用于使用Database First的EF设置吗?该方法被存根并带有一个覆盖:throw new UnintentionalCodeFirstException(); - user210757
@user210757 - 你解决了UnintentionalCodeFirstException的问题了吗? - gkb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接