Last active
September 21, 2018 04:22
-
-
Save KarateJB/3090bdbf866a53d6b9896324e346f82c to your computer and use it in GitHub Desktop.
DB Schema Initialize: Copy the descriptions from Code-first model to Table and Column in Sql Server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class DbSchemaInitializer : IDisposable | |
{ | |
private DbContext _dbContext = null; | |
public DbSchemaInitializer(DbContext dbContext) | |
{ | |
if (dbContext == null) | |
throw new ArgumentNullException("dbContext:DbContext cannot be null!"); | |
else | |
this._dbContext = dbContext; | |
} | |
/// Update the descriptions of Table and its columns from Code first model's DescriptionAttribute | |
public void UpdateTableColDescriptions() | |
{ | |
var context = this._dbContext; | |
var dbsetProps = context.GetDbSetProperties(); | |
dbsetProps.ForEach(prop => | |
{ | |
#region Get DAO type | |
//Get DbSet's model. For example, DbSet<MyModel> => MyModel | |
Type typeArgument = prop.PropertyType.GetGenericArguments()[0]; | |
#endregion | |
#region Get Table description | |
string tableName = string.Empty, desc = string.Empty; | |
Object tableNameAttr = this.getTableAttribute(typeArgument, "TableAttribute"); | |
Object descAttr = this.getTableAttribute(typeArgument, "DescriptionAttribute"); | |
if (tableNameAttr != null) | |
tableName = (tableNameAttr as System.ComponentModel.DataAnnotations.Schema.TableAttribute).Name; | |
if (descAttr != null) | |
desc = (descAttr as System.ComponentModel.DescriptionAttribute).Description; | |
if (!string.IsNullOrEmpty(tableName) && !string.IsNullOrEmpty(desc)) | |
{ | |
//Sync to database | |
this.syncTableDescription(context, tableName, desc); | |
} | |
#endregion | |
#region Get Columns description | |
if (!string.IsNullOrEmpty(tableName)) | |
{ | |
List<string> cols = this.getColsFromTable(context, tableName); | |
var methodProp = typeof(AttributeUtility).GetMethod("GetPropertyAttributes"); | |
cols.ForEach(col => | |
{ | |
List<Object> propDescAttrs = this.getPropAttribute(typeArgument, col, "DescriptionAttribute"); | |
if (propDescAttrs != null && propDescAttrs.Count > 0) | |
{ | |
string colDesc = (propDescAttrs[0] as System.ComponentModel.DescriptionAttribute).Description; | |
Debug.WriteLine($"{tableName}.{col} = {colDesc}"); | |
//Sync to database | |
this.syncColDescription(context, tableName, col, colDesc); | |
} | |
}); | |
} | |
#endregion | |
}); | |
} | |
/// Get attribute of class | |
private object getTableAttribute(Type typeArgument, string attribute) | |
{ | |
var method = typeof(AttributeUtility).GetMethod("GetClassAttributes"); | |
var generic = method.MakeGenericMethod(typeArgument); | |
var result = generic.Invoke(null, new object[] { false }); | |
var dics = (result as Dictionary<string, object>); | |
Object value = null; | |
if (dics.TryGetValue(attribute, out value)) | |
return value; | |
else | |
return null; | |
} | |
/// Get attribute of property | |
private List<object> getPropAttribute(Type typeArgument, string propName, string attribute) | |
{ | |
var method = typeof(AttributeUtility).GetMethod("GetPropertyAttributes"); | |
var generic = method.MakeGenericMethod(typeArgument); | |
var result = generic.Invoke(null, new object[] { propName, false }); | |
var dics = (result as Dictionary<string, List<object>>); | |
List<Object> values = null; | |
if (dics.TryGetValue(attribute, out values)) | |
return values; | |
else | |
return null; | |
} | |
/// Get all Column names of a Table | |
private List<string> getColsFromTable(DbContext context, string tableName) | |
{ | |
string sql = $@" | |
SELECT COLUMN_NAME | |
FROM INFORMATION_SCHEMA.COLUMNS | |
WHERE TABLE_NAME = '{tableName}' AND TABLE_SCHEMA='dbo'"; | |
return context.Database.SqlQuery<string>(sql).ToList(); | |
} | |
/// Use sp_addextendedproperty/sp_updateextendedproperty to update the Description of a Table | |
private void syncTableDescription(DbContext context, string tableName, string description) | |
{ | |
string sql = string.Empty; | |
int rslt = 0; | |
try | |
{ | |
sql = $@" | |
EXEC sp_updateextendedproperty | |
@name = N'MS_Description', | |
@value = '{description}', | |
@level0type = N'Schema', @level0name = dbo, | |
@level1type = N'Table', @level1name = {tableName}"; | |
rslt = context.Database.ExecuteSqlCommand(sql); | |
} | |
catch (Exception ex) | |
{ | |
sql = $@" | |
EXEC sp_addextendedproperty | |
@name = N'MS_Description', | |
@value = '{description}', | |
@level0type = N'Schema', @level0name = dbo, | |
@level1type = N'Table', @level1name = {tableName}"; | |
context.Database.ExecuteSqlCommand(sql); | |
} | |
} | |
/// Use sp_addextendedproperty/sp_updateextendedproperty to update the Description of a Column | |
private void syncColDescription(DbContext context, string tableName, string colName, string description) | |
{ | |
string sql = string.Empty; | |
try | |
{ | |
sql = $@" | |
EXEC sp_updateextendedproperty | |
@name = N'MS_Description' | |
,@value = '{description}' | |
,@level0type = N'Schema', @level0name = dbo | |
,@level1type = N'Table', @level1name = {tableName} | |
,@level2type = N'Column', @level2name = ""{colName}"";"; | |
context.Database.ExecuteSqlCommand(sql); | |
} | |
catch (Exception ex) | |
{ | |
sql = $@" | |
EXEC sp_addextendedproperty | |
@name = N'MS_Description' | |
,@value = '{description}' | |
,@level0type = N'Schema', @level0name = dbo | |
,@level1type = N'Table', @level1name = {tableName} | |
,@level2type = N'Column', @level2name = ""{colName}"""; | |
context.Database.ExecuteSqlCommand(sql); | |
} | |
} | |
/// <summary> | |
/// Dispose | |
/// </summary> | |
public void Dispose() | |
{ | |
if (this._dbContext != null) | |
{ | |
this._dbContext.Dispose(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment