相同实体类型(任何 ORM)的不同版本用于不同的角色/授权级别
例如,考虑一下:
public interface IStaff
{
FullName name { get; set; }
EMailAddress email_address { get; set; }
SocialInsuranceId ssn { get; set; }
PositiveInt age { get; set; }
Address home_address { get; set; }
}
对于某些用户,视图模型只需要 name
和 email_address
。 其他人可能拥有包含这些属性以及 ssn
、age
和 home_address
的视图模型。假设还有一位统计学家,其视图获取 age
和 home_address
。
现在,我可以通过接口继承将其拆分为 IStaffBasic
、IStaffDetails
和 IStaffStats
,以将给定视图模型中的 API 限制为适当的属性。
但是,当通过网络从数据服务检索该实体时,它仍将包含附加详细信息,这是绝对不能发生的。
那么,最好
(A) 为每个版本创建完全不同的实体类型,从而对每种类型进行许多额外的近乎重复的查询操作,从而在一定程度上污染服务层 API,或者
(B) 始终返回 Staff
实体,但 (1) 从服务中返回它们,并根据服务上的授权检查将排除的属性设置为 null
以及 (2)如上所述,在视图模型中使用有限的接口,或者
(C) 使用我没有考虑过但你要告诉我的非常优雅的模式或解决方案。
选项 A 在视图模型级别似乎更干净,但服务 API 会很糟糕。选项 B 似乎增加了服务器上实体处理的复杂性,但更好地遵守了开放-封闭原则。
想法?
Consider, for example:
public interface IStaff
{
FullName name { get; set; }
EMailAddress email_address { get; set; }
SocialInsuranceId ssn { get; set; }
PositiveInt age { get; set; }
Address home_address { get; set; }
}
For some users, the viewmodel will only require name
and email_address
.
Others may have a viewmodel that includes those properties plus ssn
, age
and home_address
. Let's say there is also a statistician, whose view gets age
and home_address
.
Now, I could split this out into IStaffBasic
, IStaffDetails
, and IStaffStats
with interface inheritance to limit the API in a given viewmodel to the appropriate properties.
However, when this entity is retrieved from the data service across the wire, it will still include the additional details, which must not occur.
So, would it be better to
(A) create wholly different entity types for each of these versions, somewhat polluting the service layer API with many additional near-duplicate query operations for each type, or
(B) always return a Staff
entity, but (1) return them from the service with excluded properties set to null
based on the authorization check at the service and (2) use limited interfaces within the viewmodels as described above, or
(C) use the very elegant pattern or solution that I haven't considered, but about which you're going to tell me.
Option A seems cleaner at the viewmodel level, but the service API is going to be nasty. Option B seems to add complexity to entity handling on the server, but better adherence to the open-closed principle.
Thoughts?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
投影是可行的方法 - 结合选项 A 和 B。
您的 ORM 应该只与单个实体类型
Staff
交互,因此您只需维护(和扩展)一组映射、查询等。但是,您还可以创建适合每种安全场景的不同类(
IStaffBasic
、IStaffDetails
等),将Staff
实例投影到这些类中,并通过网络返回投影对象:某些 ORM 支持投影作为框架功能,但如果需要,您可以在服务层中手动执行此操作。
Projection is the way to go - combine options A and B.
Your ORM should only interact with a single entity type,
Staff
, so you only have to maintain (and extend) a single set of mappings, queries, and so forth.However, you'll also create different classes suitable for each security scenario (
IStaffBasic
,IStaffDetails
, etc.), project theStaff
instances into those, and return the projected objects over the wire:Some ORMs support projection as a framework feature, but if need be, you can do it manually in your service layer.