EF Core 从方法而不是 属性 中保存值

EF Core save value from method instead of property

我喜欢从方法而不是 属性 向列中添加一些数据。这在 EF Core 中有可能吗?

例如,配置代码可能如下所示:

internal class MyEntityTypeConfiguration : IEntityTypeConfiguration<MyEntity>
{
    public void Configure(EntityTypeBuilder<MyEntity> builder)
    {
        builder.ToTable("Table1");

        // Add column "Value1" and set it with the return value of myEntity.GetValue()
        builder.Property<string>("Value1").WithValue(myEntity => myEntity.GetValue()); // TODO create WithValue

        builder.HasKey(o => o.Id);
    }
}

在这种情况下,WithValue 方法将不存在。

示例:

例如,我将保存 2 个实体。

  1. GetValue() 对于实体​​ 1 returns "I am Entity 1"
  2. GetValue() 对于实体​​ 2 returns "I am Entity 2"

然后我喜欢在Value1

列中存储"I am Entity 1""I am Entity 2"

解决方案

Jairo 的 ValueGenerator 解决方案非常适合我!我做了 WithValue 这样的:

internal class ValueRetriever<TEntityEntry, TResult> : Microsoft.EntityFrameworkCore.ValueGeneration.ValueGenerator<TResult>
{
    private readonly Func<TEntityEntry, TResult> _retrieve;

    public ValueRetriever(Func<TEntityEntry, TResult> retrieve)
    {
        _retrieve = retrieve;
    }

    public override bool GeneratesTemporaryValues => false;

    public override TResult Next(EntityEntry entry) => _retrieve((TEntityEntry)entry.Entity);
}

WithValue 分机:

public static void WithValue<TEntityEntry, TResult>(this PropertyBuilder<TResult> propertyBuilder, Func<TEntityEntry, TResult> retrieve)
{
    propertyBuilder.HasValueGenerator((property, type) => new ValueRetriever<TEntityEntry, TResult>(retrieve));
}

用法:

builder
   .Property<string>("Value1")
   .WithValue<MyEntity, string>(myEntity => myEntity.GetValue()); 

我觉得shadow properties可以帮到你。

EF Core 影子属性允许您定义和保留非域数据,即未在 类 中定义的数据。您在 DbContext 中定义影子属性,并使用 DbContext 设置它们的值。

定义它们:

modelBuilder.Entity<MyEntity>().Property<String>("Value1");

设置它们的值:

dbContext.Entry(myEntity).Property("Value1").CurrentValue = myEntity.GetValue();

此外,您可以使用 HasValueGenerator 扩展方法来设置可以从您的实体获取值的值生成器:

modelBuilder.Entity<MyEntity>().Property<string>("Value1").HasValueGenerator<ValueGenerator>();

价值创造者:

class ValueGenerator : Microsoft.EntityFrameworkCore.ValueGeneration.ValueGenerator
{
    public override bool GeneratesTemporaryValues => false;

    protected override object NextValue(EntityEntry entry) => ((MyEntity) entry.Entity).GetValue();
}

实体:

class MyEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string GetValue() => $"My Name: {Name}";
}