【问题标题】:How to add the support for structured annotations to the EF Core SqlServer target builder?如何向 EF Core SqlServer 目标构建器添加对结构化注释的支持?
【发布时间】:2018-01-11 21:28:10
【问题描述】:

使用接受object 类型参数的HasAnnotation 方法向EF 模型添加纯字符串注释很容易,但尝试添加结构化注释会在构建迁移时出错:

        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 注入有助于序列化结构化注释的方法?

为什么我需要它?只是试图在一个地方收集所有数据库元数据。而元通常是结构化信息。

【问题讨论】:

    标签: .net entity-framework annotations entity-framework-core entity-framework-core-migrations


    【解决方案1】:

    据我所知(关于这方面的信息很少,如果有的话),这个想法是使用简单的名称/值对,其中的值是原始类型(stringint、@987654328 @、DateTime 等加上 enums) 和名称构成了结构。所有 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>();
        }
    }
    

    【讨论】:

    • 在撰写问题时,我曾尝试过 POCO,但结果相同(错误)...但现在我将对其进行更多试验。
    • 嗯,我在发布之前已经尝试过了,它确实有效。对于您的第一个示例,代码类似于 if (value is ValueTuple&lt;string, string&gt; vt) return $"new ValueTuple&lt;string, string&gt;({Literal(vt.Item1)}, {Literal(vt.Item2)})"; 并且它在迁移 designer.cs 文件中生成了正确的 HasAnnotation。确保通过将 throw new Exception("Blah"); 临时放在被覆盖方法的开头来调用您的服务。如果这很重要,则使用 E​​FC 2.0.1 进行测试。
    • 是的,这很有效,而且非常令人惊讶的方式(直接将文本插入迁移源)......我对“液体代码向导”有一种很好的感觉。非常感谢你。至少 ef core 中的迁移以灵活的方式完成(我对 EF core 日志记录和 EF core DI“仅容器”方式非常不满意)。
    • Ivan,我可以请你谈谈你对这些问题的想法(首先是继续尝试重用 EF COre 元模型):1)stackoverflow.com/questions/48242973/…2)stackoverflow.com/questions/47744989/…
    • 嗨@Roman,当然,有时间我会的。但请注意,我没有参与 EF Core 开发,所以我所有的帖子都是基于文档、试验和探索源代码 :)
    猜你喜欢
    • 1970-01-01
    • 2017-11-30
    • 1970-01-01
    • 2017-12-07
    • 2021-04-02
    • 2016-02-17
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    相关资源
    最近更新 更多