在EF7(核心)OnModelCreating中使用自定义属性 [英] Using a custom attribute in EF7 (core) OnModelCreating

查看:441
本文介绍了在EF7(核心)OnModelCreating中使用自定义属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 DefaultAttribute 定义,如下所示:

I have a DefaultAttribute defined like so:

[AttributeUsage(AttributeTargets.Property)]
public class DefaultAttribute : Attribute
{
    /// <summary>
    /// Specifies this property has a default value upon creation.
    /// </summary>
    /// <param name="defaultValue">The default value of the property.</param>
    /// <param name="useAsLiteral">Set to true if the value is <em>not</em> quoted in the DDL.</param>
    public DefaultAttribute(object defaultValue, bool useAsLiteral = false)
    {
        DefaultValue = defaultValue;
        UseAsLiteral = useAsLiteral;
    }

    public object DefaultValue { get; private set; }

    /// <summary>
    /// True if the default value is not quoted in the DDL
    /// </summary>
    public bool UseAsLiteral { get; private set; }
}

我已经用此属性装饰了几个实体,如下所示:

I have decorated several of my entities with this attribute, like so:

public class MyEntity
{
    . . . (other properties) . . .
    [StringLength(200)]
    [Required]
    [Default("My Default Description!")]
    public string Description { get; set; }
}

然后,在数据库上下文的OnModelCreating方法中,编写了以下内容代码:

Then, in my OnModelCreating method in my database context, I wrote the following code:

//examine custom annotations for shaping the schema in the database.
foreach (var entityType in builder.Model.GetEntityTypes())
    foreach (var property in entityType.GetProperties())
    {
        var annotations = property.GetAnnotations();

        // evaluate default values
        var defaultAnnotation = annotations.FirstOrDefault(x => x.Name == typeof(DefaultAttribute).FullName);
        if (defaultAnnotation != null)
        {
            var defaultValue = defaultAnnotation.Value as DefaultAttribute;
            if (defaultValue == null) continue;

            if (defaultValue.UseAsLiteral)
                property.Npgsql().DefaultValueSql = defaultValue.DefaultValue.ToString();
            else
                property.Npgsql().DefaultValue = defaultValue.DefaultValue;
        }
    }

我期望添加迁移时,(以及后续数据库更新)是默认值为我的默认描述!。对于 MyEntity 说明列...,但是不是这种情况。

My expectation, when adding a migration, (and subsequent database update) is that there would be a default value of "My Default Description!" for the Description column of MyEntity... however, that is not the case.

我没有收到任何错误,但是没有按照我所怀疑的那样工作,并且很难进入具有断点的 OnModelCreating

I'm not getting any errors, but it's not doing as I would suspect, and stepping into OnModelCreating with a breakpoint is also inexplicably difficult to do.

我这样做正确吗?就是行不通吗? EF7不支持吗?还是我的PostgreSQL实现不支持它?任何见识将不胜感激。

Am I doing this correctly? Does it just not work? Is it just not supported in EF7? Or is it not supported in my PostgreSQL implementation? Any insight would be appreciated.

更新
使用@IvanStoev的答案,我能够将此进行一些较小的修改(.NET Core中的反映与传统有所不同):

UPDATE Using @IvanStoev's answer, I was able to get this to work with some minor modifiactions (Reflection in .NET Core a bit different from traditional):

//examine custom annotations for shaping the schema in the database.
foreach (var entityType in builder.Model.GetEntityTypes())
    foreach (var property in entityType.GetProperties())
    {
        var memberInfo = property.PropertyInfo ?? (MemberInfo)property.FieldInfo;
        var defaultValue = memberInfo?.GetCustomAttribute<DefaultAttribute>();
        if (defaultValue == null) continue;
        if (defaultValue.UseAsLiteral)
            property.Npgsql().DefaultValueSql = defaultValue.DefaultValue.ToString();
        else
            property.Npgsql().DefaultValue = defaultValue.DefaultValue;
    }

这很像冠军。

推荐答案

EF Core对您的自定义属性一无所知,因此无法发现它并将其作为注释公开(通常这是另一回事,不一定与之关联)属性)。

EF Core knows nothing about your custom attribute, so there is no way it to be discovered and exposed as annotation (which in general is a different thing and not necessarily associated with attribute).

您必须手动从 PropertyInfo FieldInfo 如果存在:

You have to extract the attribute manually from PropertyInfo or FieldInfo when present:

foreach (var entityType in builder.Model.GetEntityTypes())
    foreach (var property in entityType.GetProperties())
    {
        var memberInfo = property.PropertyInfo ?? (MemberInfo)property.FieldInfo;
        if (memberInfo == null) continue;
        var defaultValue = Attribute.GetCustomAttribute(memberInfo, typeof(DefaultAttribute)) as DefaultAttribute;
        if (defaultValue == null) continue;
        if (defaultValue.UseAsLiteral)
            property.Npgsql().DefaultValueSql = defaultValue.DefaultValue.ToString();
        else
            property.Npgsql().DefaultValue = defaultValue.DefaultValue;
    }

这篇关于在EF7(核心)OnModelCreating中使用自定义属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆