EF6 根据包含 class 的属性设置 属性 的 MaxLength

EF6 Set MaxLength of a property based on attribute of the containing class

情况:

我有一个baseclassLookup,如下:

 public abstract class Lookup : DeactivatableDomainModel {
    [Required]
    [Key]
    public int ID { get; set; }

    [Required]
    public string Description { get; set; }

    [Required]
    public int DisplayOrder { get; set; }
  }

我还创建了一个属性 IsLookup:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class IsLookup : Attribute {
  public int DescriptionLength { get; set; }
  public int CodeLength { get; set; }

  public IsLookup(int DescriptionLength, int CodeLength = 0) {
    this.DescriptionLength = DescriptionLength;
    this.CodeLength = CodeLength;
  }
}

目标是能够创建以下声明:

[IsLookup(40)]
public class TestCategory : Lookup { }

...并使用 OnModelCreating 将 属性 描述的 MaxLength 设置为 40。

我已经能够编写一些看起来应该可以工作的代码,并且 add-migration 运行得很好,但是生成的迁移没有设置最大长度:

  protected override void OnModelCreating(DbModelBuilder modelBuilder) {
    base.OnModelCreating(modelBuilder);

    modelBuilder.Properties()
      .Where(p => p.Name == "Description" && p.DeclaringType.GetCustomAttributes(false).OfType<IsLookup>().FirstOrDefault() != null)
      .Configure(
        c => c.HasMaxLength(((IsLookup)c.ClrPropertyInfo.DeclaringType.GetCustomAttributes(typeof(IsLookup), false).FirstOrDefault()).DescriptionLength)
      );

  }

结果是:

  CreateTable(
      "Lookups.TestCategories",
      c => new {
        ID = c.Int(nullable: false, identity: true),
        Description = c.String(nullable: false),
        DisplayOrder = c.Int(nullable: false),
        Active = c.Boolean(nullable: false),
        RowVersion = c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion"),
      })
      .PrimaryKey(t => t.ID);

所以,问题是...为什么 Description 没有在迁移代码中设置其长度?这可能吗?

<gripe>如果有调试的方法add-migration,那就简单多了。</gripe>

我很确定 DeclaringType 会给你声明 属性 的类型,在你的例子中 Lookup class 是 Description 属性 被声明。由于 Lookup 没有 IsLookup 属性,因此不会设置任何内容。尝试先查看已注册的类型,然后在找到后设置描述列:

modelBuilder.Types()
    .Where(t => t.IsSubclassOf(typeof(Lookup)))
    .Having(x => x.GetCustomAttributes(false).OfType<IsLookup>().FirstOrDefault())
    .Configure((config, att) => {
        config.Property("Description").HasMaxLength(att.DescriptionLength);
    });