Skip to content

Instantly share code, notes, and snippets.

@KarateJB
Last active September 21, 2018 04:22
Show Gist options
  • Save KarateJB/3090bdbf866a53d6b9896324e346f82c to your computer and use it in GitHub Desktop.
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
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