在 Entity Framework Core 中,我有一个实体类,其中的属性我想从 SELECT 操作中排除,但在 INSERT 和 UPDATE 期间仍包含该属性。实体类无法修改,因此我无法添加支持字段或对类本身进行更改。如何配置此属性在查询数据时被忽略,但在保存更改时仍允许设置和更新它?
实体类如下所示:
public class MyEntity
{
public int Id { get; set; }
public string MyProperty { get; set; }
}
当从数据库加载实体时,我需要省略 MyProperty,但仍包含在 INSERT 和 UPDATE 操作中。
请注意,我不能使用这样的解决方案:
var myEntities = context.Set<MyEntity>()
.Select(e => new MyEntity
{
Id = e.Id,
// Exclude MyProperty
});
因为我事先不知道确切的实体和属性。需要此自定义配置来替换使用自定义属性的旧自定义内部 ORM
[WriteOnly]
对于旧的 ORM
[ReadOnly]
属性,我成功地用以下内容改造了逻辑:
propertyBuilder.Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore); // Avoids inserting the property
propertyBuilder.Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore); // Avoids updating the property
我想忽略OnModelCreating中的属性:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MyEntity>()
.Ignore(e => e.MyProperty);
}
并重写 SaveChanges 方法以强制修改属性:
public override int SaveChanges()
{
foreach (var entry in ChangeTracker.Entries<MyEntity>())
{
if (entry.State == EntityState.Added || entry.State == EntityState.Modified)
{
entry.Property(nameof(MyEntity.MyProperty)).IsModified = true;
}
}
return base.SaveChanges();
}
这有效地防止了属性在 SELECT 期间被具体化,但是
entry.Property(nameof(MyEntity.MyProperty)).IsModified = true;
行无法工作,因为属性 MyProperty 不再是模型的一部分
我建议有两个属性。一个公共是您的业务模型的一部分,一个私有用于持久性(我使用属性来配置模型,但当然可以使用 Fluent API 代替)
public class MyEntity
{
public int Id { get; set; }
private string _myProperty;
[NotMapped]
public string MyProperty {
get => _myProperty;
set {
_myProperty = value;
MyPropertyDb = value;
}
}
[Column("MyProperty")]
private string MyPropertyDb { get; set; }
}
重点是设置
MyProperty
将写入其支持字段并更新 MyPropertyDb
。获取该值只会检索支持字段并忽略可能已从数据库读取的 MyPropertyDb
的值。