【问题标题】:EF Core save value from method instead of propertyEF Core 从方法而不是属性中保存值
【发布时间】:2020-05-03 14:32:12
【问题描述】:

我喜欢从方法而不是属性向列添加一些数据。这在 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 返回 "I am Entity 1"
  2. GetValue() 实体 2 返回 "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()); 

【问题讨论】:

  • 您到底想解决什么问题?类型 MyEntity 将始终具有相同的值。为什么要保存到数据库中?
  • 保存多个实体时,值当然会不同
  • 好的。我仍然不确定你想要实现什么。你能详细说明一下吗?
  • 有一种方法可以将 EF Core 配置为使用 SQL 生成的属性值。
  • 添加示例,但也感谢 Jairo Alfaro 的解决方案 :)

标签: c# entity-framework-core entity-framework-core-3.0


【解决方案1】:

我觉得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}";
}

【讨论】:

  • 啊,谢谢。不幸的是,我只能更改 MyEntityTypeConfiguration 而不能更改调用代码。因此我需要 EntityTypeBuilder 上的一些东西
  • 使用 HasValueGenerator 扩展方法可能是一个选项,请查看我的更改。
  • 太棒了! ValueGenerator 方法正是我一直在寻找的地方:)
猜你喜欢
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多