如何使用 Entity Framework Core/6 将 DbSet 设置为只读
我正在尝试使用 EntityFramework Core/6 与数据库交互。我希望 DbContext 类尽可能精简。我这样做的一种方法是将任何存储库构建配置移动到像这样的特定类
public class ProductViewConfiguration : IEntityTypeConfiguration<ProductView>
{
public void Configure(EntityTypeBuilder<ProductView> builder)
{
builder.ToTable("viewProducts");
}
}
如您所见,我正在尝试为视图配置 DbSet
。所以我不需要跟踪这个存储库中的任何更改。因此,我需要使用 AsNoTracking()
构建/配置此 DbSet
。
如何使用 EntityTypeBuilder
构建器将 DbSet 配置为只读?
I am trying to use EntityFramework Core/6 to interact with the database. I would like to keep the DbContext class as slim and possible. One way I am doing it is by moving any repository building configuration a specific class like this
public class ProductViewConfiguration : IEntityTypeConfiguration<ProductView>
{
public void Configure(EntityTypeBuilder<ProductView> builder)
{
builder.ToTable("viewProducts");
}
}
As you can see, I am trying to configure DbSet<ProductView>
for a view. so I don't need to track any changes in this repository. So I somehow need to build/configure this DbSet<>
with AsNoTracking()
.
How can I use the EntityTypeBuilder<>
builder to configure the DbSet as a read-only?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当使用您想要视为只读的视图时,您可以将实体属性设置器标记为受保护,以阻止任何未来代码期望可以设置这些实体,然后在 DbContext 本身中
:使用 AsNoTracking 的注意事项是,从基于 ProductView 的查询返回的所有实体都不会被跟踪,因此,如果 ProductView 实体具有您想要更新的导航属性(出于任何原因),那么这些实体不会被跟踪。
提供运行时保护而不限制相关实体或 ProductView 实体可能滑入更改跟踪器的任何其他方式的另一种折衷方案是在实体中实现
protected
setter,然后覆盖OnSaveChanges
在 DbContext 中检查 ProductView 和/或任何其他只读视图的插入、更新和删除实体。如果找到,则抛出异常。这些实体可以用诸如 [ReadOnlyEntity] 之类的属性来标记,您可以在提交更改之前检查该属性。您在实体内的属性设置器中有一个编译时防护,这应该阻止滥用或至少提示新开发人员提出问题。虽然主要守卫是在运行时,但如果它触发了异常,如果有人忽视了既定的规则,那么团队内部将有理由进行严肃的讨论。 (如果他们干扰了更改protected
设置器,那么没有什么可以阻止他们删除[ReadOnlyEntity]
属性,并且DbContext可能仍然无法尝试通过视图进行更新。)目标是让开发人员更容易理解所使用的模式及其原因,而不是试图让他们很难犯错误。总的来说,当涉及到实体时,我尝试使用 DDD 方法,其中对 setter 的访问受到限制。实体构造由工厂方法处理,其中构造函数的作用域为内部,而大多数“复杂”更新是通过方法而不是单个属性设置器在实体中传递的。这可确保更新提供所有必要的详细信息,以确保实体始终处于有效状态。可选的独立属性/除了长度/范围/空检查之外没有复杂的验证,具有公共设置器。只读实体根本没有可见的设置器。如果开发人员接受了所使用模式的指导,那么在处理没有设置器的实体时,第一个假设应该是“这是一个只读实体”,并且至少会引发有关其需求的讨论。
When working with views which you want to treat as read-only, you can mark entity property setters as
protected
to discourage any future code from expecting that these entities can be set, then in the DbContext itself:A caveat of using
AsNoTracking
is that all entities returned from a query based off of ProductViews won't be tracked, so if the ProductView entity has navigation properties that you would want to update (for any reason) then those won't be tracked.Another compromise which provides runtime protection without the limitation on related entities or any other way a ProductView entity might slip into a Change Tracker would be to implement the
protected
setters in the entity, then override theOnSaveChanges
in the DbContext to inspect inserted, updated, and deleted entities for ProductView and/or any other read-only view. If found, throw an exception. These entities could be marked by an Attribute such as [ReadOnlyEntity] which you could inspect for prior to committing changes. You have a compile-time guard in the property setters within the entity which should deter abuse or at least prompt questions from new developers. The main guard is at runtime though, but if it were ever to trigger that exception that would be grounds for a serious talk within the team if someone ignored the established rules. (There's nothing stopping them from removing the[ReadOnlyEntity]
attribute if they are messing with changingprotected
setters and the DbContext would likely still fail attempting to update via the view.) Ultimately the goal is make it easy for developers to understand the patterns used and reasons for them rather than trying to make it hard for them to make a mistake.Overall when it comes to entities I try to use DDD approaches where access to setters is restricted. Entity construction is handled by factory methods where the constructor is scoped
internal
, while most "complex" updates are handed in the entity via methods rather than individual property setters. This ensures that updates provide all necessary details to ensure an entity is always in a valid state. Optional, independent properties /w no complex validation beyond length/range/null checks have public setters. Read-only entities would simply have no visible setters. If developers are instructed in the patterns used, the first assumption when dealing with an entity with no setters should be "This a read-only entity" and at least prompt a discussion about their requirement.