2017-08-15 97 views
2

我有我使用的是Azure的移動服務下面的代碼,第一實體框架代碼:如何在EF code-first和Azure中創建默認約束?

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); 
} 
} 

如上所述,該代碼應該被刪除的列上添加一個默認約束,但它確實不做任何事情。我希望實現與EF代碼優先級相同的以下SQL語句:

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

顯然,我必須做錯了什麼。任何人都可以將我指向正確的方向嗎?

回答

1

AFAIK,數據庫的默認值是EF Core的一部分,有關更多詳細信息,請參閱Default Values

根據您的要求,您嘗試爲Azure移動服務表的系統列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

+1

由於布魯斯。你的代碼運行良好。實際上,我只需要添加EntityTableSqlGenerator並按原樣離開OnModelCreating。無論如何,已創建「已刪除」列的默認約束。爲什麼我需要爲OnModelCreating中的已刪除列設置默認值? – ata6502

+0

我以爲'Deleted'列沒有默認約束,謝謝提醒我。要爲自定義列設置默認值,可以參考其餘部分。 –

+0

讓我澄清一下:MyEntityTableSqlGenerator的用途是設置Default約束的值。 OnModelCreating的目的是創建Default約束。這是對的嗎?如果是這樣,我可能已經運行創建了默認約束的OnModelCreating。 – ata6502