如何在EF代码优先和Azure中创建默认约束?

时间:2017-08-15 13:17:07

标签: c# entity-framework azure azure-mobile-services

我有以下代码优先的实体框架代码,我使用的是Azure Mobile服务:

public class BookContext : DbContext
{
private const string connectionStringName = "Name=MS_TableConnectionString";

public BookContext() : base(connectionStringName) { } 

// The collections queried directly.
public DbSet<Book> Books{ get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Standard code to add the "service" columns such as CreatedAt, UpdatedAt, and Deleted.
    modelBuilder.Conventions.Add(
        new AttributeToColumnAnnotationConvention<TableColumnAttribute, string>(
            "ServiceTableColumn", (property, attributes) => attributes.Single().ColumnType.ToString()));

    // Add a default value 0 on the Deleted column. The following code does not work.
    modelBuilder.Entity<Book>()
                .Property(p => p.Deleted)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
}
}

如上所述,代码应该在Deleted列上添加默认约束,但它不会执行任何操作。我希望实现与EF代码优先相同的以下SQL语句:

ALTER TABLE dbo.Books ADD CONSTRAINT DF_BooksDeleted DEFAULT 0 FOR Deleted

显然,我一定是做错了。有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:1)

AFAIK,数据库的默认值是EF Core的一部分,有关详细信息,请参阅Default Values

根据您的要求,您尝试为Azure Mobile服务表的系统列Deleted设置默认值。我假设您可以覆盖EntityTableSqlGenerator.cs并添加用于设置系统列Deleted和您的自定义列的默认值的逻辑,如下所示:

<强> MyEntityTableSqlGenerator.cs

public class MyEntityTableSqlGenerator : EntityTableSqlGenerator
{
    protected override void UpdateTableColumn(ColumnModel columnModel, TableColumnType tableColumnType)
    {
        //for system column deleted
        switch (tableColumnType)
        {
            case TableColumnType.Deleted:
                columnModel.DefaultValue = 0;
                break;
        }
        base.UpdateTableColumn(columnModel, tableColumnType);
    }

    protected override void Generate(CreateTableOperation createTableOperation)
    {
        //for your custom columns
        foreach (ColumnModel column in createTableOperation.Columns)
        {
            TableColumnType tableColumnType = this.GetTableColumnType(column);
            if (tableColumnType == TableColumnType.None)
            {
                if (column.Annotations.Keys.Contains("DefaultValue"))
                {
                    var value = Convert.ChangeType(column.Annotations["DefaultValue"].NewValue, column.ClrDefaultValue.GetType());
                    column.DefaultValue = value;
                }
            }
        }

        //for system columns
        base.Generate(createTableOperation);
    }
}

修改Configuration.cs并添加自定义SqlGenerator:

public Configuration()
{
    SetSqlGenerator("System.Data.SqlClient", new MyEntityTableSqlGenerator());
}

然后,按如下方式修改OnModelCreating方法:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{   
    //set default value for your custom columns
    modelBuilder.Entity<Tag>()
        .Property(p => p.Status)
        .HasColumnName("Status")
        .HasColumnAnnotation("DefaultValue","false");

    modelBuilder.Conventions.Add(
        new AttributeToColumnAnnotationConvention<TableColumnAttribute, string>(
            "ServiceTableColumn", (property, attributes) => attributes.Single().ColumnType.ToString()));

}

<强>结果:

enter image description here