EF Core HasValueGenerator

Использую Microsoft.EntityFrameworkCore (6.0.8) в своём pet-проекте. Для сопоставления свойств класса и полей в таблицах использую реализацию IEntityTypeConfiguration<TEntity>.

Пример:

Models.cs

    public class ParentClass
    {
      public int Id {get;set;}
      public virtual ICollection<ChildClass> Childs {get;set;}
    }

    public class ChildClass
    {
      public int Id {get;set;}
      public int ParentId {get;set;}
      public int ChildNo {get;set;}
      public ParentClass ParentClass {get;set;}
    }

ModelsConfigurations.cs

    public class ParentClassConfiguration: IEntityTypeConfiguration<ParentClass>
    {
      builder.ToTable("parents");

      builder.Property(x => x.Id)
             .HasColumnName("id")
             .ValueGeneratedOnAdd()
             .IsRequired();

      builder.HasKey(x => x.Id)
             .HasName("pk_parents");

      builder.Ignore(x => x.Childs );
    }

      public class ChildClassConfiguration: IEntityTypeConfiguration<ChildClass>
      {
        builder.ToTable("childs");

        builder.Property(x => x.Id)
               .HasColumnName("id")
               .ValueGeneratedOnAdd()
               .IsRequired();

        builder.Property(x => x.ParentId)
               .HasColumnName("parent_id")
               .IsRequired();

        builder.Property(x => x.ChildNo)
               .HasColumnName("child_no")
               .HasValueGenerator(typeof(ChildNoGenerator))
               .IsRequired();

        builder.HasKey(x => x.Id)
               .HasName("pk_childs");

        builder.HasOne(x => x.ParentClass)
               .WithMany(y => y.Childs)
               .IsRequired()
               .ForeignKey(x => x.ParentId)
               .HasConstraintName("fk_childs_parents")
               .OnDelete(DeleteBehavior.SetNull);

        builder.Ignore(x => x.ParentClass);
      }

ChildNoGenerator.cs

        public class ChildNoGenerator: ValueGenerator<int>
        {
          public override bool GeneratesTemporaryValues => false;

          public override int Next(EntityEntry entry) => GetNextChildNo();

          private static int GetNextChildNo()
          {
            /*Вот в этом месте мне необходимо как-то получить ChildClass.ParentId
              (Id родительского экземпляра) и по нему через Linq получить
              максимальный ChildNo из коллекции родителя. К нему
              прибавить 1 и вернуть результат*/
            
            var result = ???;

            return result + 1;
          }
        }

На уровне БД я знаю, что это можно сделать через триггеры, но есть желание перенести эту генерацию на уровень приложения (просто захотелось). Я понимаю, что здесь мне пригодится использовать тот же DBContext, который я использую в приложении, но вопрос остается - как мне получить ChildClass.ParentId в генераторе значения?


Ответы (1 шт):

Автор решения: User
public class ChildNoGenerator : ValueGenerator<int>
{
    public override bool GeneratesTemporaryValues => false;

    public override int Next(EntityEntry entry) => GetNextChildNo(entry.Entity as ChildClass);

    private static int GetNextChildNo(ChildClass entity)
    {
            /*Вот в этом месте мне необходимо как-то получить ChildClass.ParentId
              (Id родительского экземпляра) и по нему через Linq получить
              максимальный ChildNo из коллекции родителя. К нему
              прибавить 1 и вернуть результат*/

        var result = ???;

        return result + 1;
    }
}

Только не понятно, зачем Вам такое правило генерации?

→ Ссылка