Как добавить поддержку структурированных аннотаций в построитель целей EF Core SqlServer?

Легко добавить простые строковые аннотации к модели EF с HasAnnotation метод, который принимает object тип аргумента, но при попытке добавить структурированные аннотации вы получите ошибки при миграции сборки:

        modelBuilder.Entity<Group>().HasAnnotation($"{GetType().FullName}.Constraint3", new ValueTuple<string,string>( "aaa", "bbb" ));

The current CSharpHelper cannot scaffold literals of type 'System.ValueTuple`2[System.String,System.String]'. Configure your services to use one that can.

        modelBuilder.Entity<Group>().HasAnnotation($"{GetType().FullName}.Constraint2", new[] { "aaa", "bbb" });

The current CSharpHelper cannot scaffold literals of type 'System.String[]'. Configure your services to use one that can.

Есть ли у нас способ внедрить метод в target builder что поможет сериализовать структурированные аннотации?

Зачем мне это нужно? Просто пытаюсь собрать всю базу метаданных в одном месте. А мета это обычно структурированная информация.

1 ответ

Решение

Насколько я понимаю (информации об этом немного, если вообще есть), идея в том, чтобы использовать простые пары имя / значение, где значения являются примитивными типами (string, int, decimal, DateTime и т. д. плюс enum s) и имена образуют структуру. Все аннотации EF Core следуют этому принципу. Например, Имя: "SqlServer:ValueGenerationStrategy" Тип: SqlServerValueGenerationStrategy и т.п.

Вероятно, проще всего просто следовать этой конвенции. Но в любом случае, ответственная служба ICSharpHelper - UnknownLiteral метод. И реализация по умолчанию находится в CSharpHelper учебный класс.

Таким образом, вы можете извлечь из него, переопределить UnknownLiteral метод и сделайте свою (предварительную) обработку там:

using Microsoft.EntityFrameworkCore.Design.Internal;

public class MyCSharpHelper : CSharpHelper
{
    public override string UnknownLiteral(object value)
    {
        // Preprocess the value here...
        return base.UnknownLiteral(value);
    }
}

тогда замените стандартную услугу своей:

using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.DependencyInjection;

public class MyDesignTimeServices : IDesignTimeServices
{
    public void ConfigureDesignTimeServices(IServiceCollection services)
    {
        services.AddSingleton<ICSharpHelper, MyCSharpHelper>();
    }
}