如何使用 Entity Framework Core/6 将 DbSet 设置为只读
How can I set a DbSet as readonly with Entity Framework Core/6
我正在尝试使用 EntityFramework Core/6 与数据库进行交互。我想让 DbContext class 尽可能苗条。我这样做的一种方法是将任何存储库构建配置移动到特定的 class 像这样
public class ProductViewConfiguration : IEntityTypeConfiguration<ProductView>
{
public void Configure(EntityTypeBuilder<ProductView> builder)
{
builder.ToTable("viewProducts");
}
}
如您所见,我正在尝试为视图配置 DbSet<ProductView>
。所以我不需要跟踪这个存储库中的任何更改。所以我不知何故需要 build/configure 这个 DbSet<>
和 AsNoTracking()
.
如何使用 EntityTypeBuilder<>
构建器将 DbSet 配置为只读?
在处理要视为 read-only 的视图时,您可以将实体 属性 setter 标记为 protected
以阻止任何未来的代码期望可以设置这些实体,然后在 DbContext 本身中:
protected DbSet<ProductView> ProductViewsProtected { get; set; }
public IQueryable<ProductView> ProductViews => ProductViewsProtected.AsNoTracking();
使用 AsNoTracking
的一个警告是,不会跟踪从基于 ProductView 的查询返回的所有实体,因此如果 ProductView 实体具有您想要更新的导航属性(出于任何原因) ) 那么这些将不会被跟踪。
提供运行时保护而不限制相关实体或 ProductView 实体可能滑入更改跟踪器的任何其他方式的另一种妥协是在实体中实现 protected
setter,然后覆盖 OnSaveChanges
在 DbContext 中检查 ProductView and/or 任何其他 read-only 视图的插入、更新和删除的实体。如果找到,则抛出异常。这些实体可以用诸如 [ReadOnlyEntity] 之类的属性标记,您可以在提交更改之前对其进行检查。您在实体内的 属性 设置器中有一个 compile-time 守卫,它应该阻止滥用或至少提示新开发人员的问题。主要守卫虽然在运行时,但如果它曾经触发过该异常,如果有人忽略了既定规则,这将成为团队内部认真讨论的理由。 (没有什么可以阻止他们删除 [ReadOnlyEntity]
属性,如果他们在更改 protected
设置器时遇到麻烦,并且 DbContext 可能仍然无法尝试通过视图更新。)最终目标是让开发人员更容易了解使用的模式及其原因,而不是试图让他们难以犯错。
总的来说,当涉及到实体时,我尝试使用限制访问 setter 的 DDD 方法。实体构造由工厂方法处理,其中构造函数的范围是 internal
,而大多数“复杂”更新是通过方法而不是单独的 属性 setter 传递给实体的。这确保更新提供所有必要的详细信息以确保实体始终处于有效状态。可选的独立属性 /w 除了 length/range/null 检查之外没有复杂的验证有 public 设置器。 Read-only 实体将根本没有可见的设置器。如果开发人员了解所使用的模式,那么在处理没有 setter 的实体时,第一个假设应该是“这是一个 read-only 实体”,并且至少会引发关于他们的要求的讨论。
我正在尝试使用 EntityFramework Core/6 与数据库进行交互。我想让 DbContext class 尽可能苗条。我这样做的一种方法是将任何存储库构建配置移动到特定的 class 像这样
public class ProductViewConfiguration : IEntityTypeConfiguration<ProductView>
{
public void Configure(EntityTypeBuilder<ProductView> builder)
{
builder.ToTable("viewProducts");
}
}
如您所见,我正在尝试为视图配置 DbSet<ProductView>
。所以我不需要跟踪这个存储库中的任何更改。所以我不知何故需要 build/configure 这个 DbSet<>
和 AsNoTracking()
.
如何使用 EntityTypeBuilder<>
构建器将 DbSet 配置为只读?
在处理要视为 read-only 的视图时,您可以将实体 属性 setter 标记为 protected
以阻止任何未来的代码期望可以设置这些实体,然后在 DbContext 本身中:
protected DbSet<ProductView> ProductViewsProtected { get; set; }
public IQueryable<ProductView> ProductViews => ProductViewsProtected.AsNoTracking();
使用 AsNoTracking
的一个警告是,不会跟踪从基于 ProductView 的查询返回的所有实体,因此如果 ProductView 实体具有您想要更新的导航属性(出于任何原因) ) 那么这些将不会被跟踪。
提供运行时保护而不限制相关实体或 ProductView 实体可能滑入更改跟踪器的任何其他方式的另一种妥协是在实体中实现 protected
setter,然后覆盖 OnSaveChanges
在 DbContext 中检查 ProductView and/or 任何其他 read-only 视图的插入、更新和删除的实体。如果找到,则抛出异常。这些实体可以用诸如 [ReadOnlyEntity] 之类的属性标记,您可以在提交更改之前对其进行检查。您在实体内的 属性 设置器中有一个 compile-time 守卫,它应该阻止滥用或至少提示新开发人员的问题。主要守卫虽然在运行时,但如果它曾经触发过该异常,如果有人忽略了既定规则,这将成为团队内部认真讨论的理由。 (没有什么可以阻止他们删除 [ReadOnlyEntity]
属性,如果他们在更改 protected
设置器时遇到麻烦,并且 DbContext 可能仍然无法尝试通过视图更新。)最终目标是让开发人员更容易了解使用的模式及其原因,而不是试图让他们难以犯错。
总的来说,当涉及到实体时,我尝试使用限制访问 setter 的 DDD 方法。实体构造由工厂方法处理,其中构造函数的范围是 internal
,而大多数“复杂”更新是通过方法而不是单独的 属性 setter 传递给实体的。这确保更新提供所有必要的详细信息以确保实体始终处于有效状态。可选的独立属性 /w 除了 length/range/null 检查之外没有复杂的验证有 public 设置器。 Read-only 实体将根本没有可见的设置器。如果开发人员了解所使用的模式,那么在处理没有 setter 的实体时,第一个假设应该是“这是一个 read-only 实体”,并且至少会引发关于他们的要求的讨论。