如何在启动时根据数据库模式检查模型
How to check the model against DB schema at startup
我有一个缓存数据库,如果模式中缺少新字段,可以简单地将其删除并重新创建。我不能为迁移而烦恼,它总是让我烦恼。
那么我该如何执行这个启动检查呢? db.Database.CompatibleWithModel
returns 正确,但是 运行 针对不匹配数据集的 Linq 查询将引发异常。
关于这类事情的大多数答案都指向迁移。
使用反射简单地测试所有数据集的可能性:
try
{
using (var db = new MyContext())
{
//db.myDataSet.Take(0).SingleOrDefault(); //The following reflection achieves what this line would do
var t = db.GetType();
var props = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in props)
{
if (!prop.PropertyType.Name.StartsWith("DbSet"))
continue;
var getMethod = prop.GetMethod;
var dataSet = getMethod.Invoke(db, null);
var dataSetType = dataSet.GetType();
var queryableType = typeof(Queryable);
var takeMethod = queryableType.GetMethod("Take");
takeMethod = takeMethod.MakeGenericMethod(dataSetType.GenericTypeArguments);
var takeResult = takeMethod.Invoke(null, new object[] { dataSet, 0 });
var sodMethod = queryableType.GetMethods().Where(m => m.Name == "SingleOrDefault" && m.GetParameters().Length == 1).Single();
sodMethod = sodMethod.MakeGenericMethod(dataSetType.GenericTypeArguments);
var finalResult = sodMethod.Invoke(null, new object[] { takeResult });
}
}
}
catch (Exception ex)
{
if (ex.InnerException != null && ex.InnerException.InnerException != null && ex.InnerException.InnerException.Message.StartsWith("Invalid column"))
{
MyHelperFunctions.MarkDatabaseForReset();
}
else
throw; //Show error to user - we didn't expect this one
}
有点粗糙,但对我有用。问题范围很广,但应该在 99% 的时间内工作(例如,代码优先数据上下文中的所有属性通常都是数据集)
我有一个缓存数据库,如果模式中缺少新字段,可以简单地将其删除并重新创建。我不能为迁移而烦恼,它总是让我烦恼。
那么我该如何执行这个启动检查呢? db.Database.CompatibleWithModel
returns 正确,但是 运行 针对不匹配数据集的 Linq 查询将引发异常。
关于这类事情的大多数答案都指向迁移。
使用反射简单地测试所有数据集的可能性:
try
{
using (var db = new MyContext())
{
//db.myDataSet.Take(0).SingleOrDefault(); //The following reflection achieves what this line would do
var t = db.GetType();
var props = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in props)
{
if (!prop.PropertyType.Name.StartsWith("DbSet"))
continue;
var getMethod = prop.GetMethod;
var dataSet = getMethod.Invoke(db, null);
var dataSetType = dataSet.GetType();
var queryableType = typeof(Queryable);
var takeMethod = queryableType.GetMethod("Take");
takeMethod = takeMethod.MakeGenericMethod(dataSetType.GenericTypeArguments);
var takeResult = takeMethod.Invoke(null, new object[] { dataSet, 0 });
var sodMethod = queryableType.GetMethods().Where(m => m.Name == "SingleOrDefault" && m.GetParameters().Length == 1).Single();
sodMethod = sodMethod.MakeGenericMethod(dataSetType.GenericTypeArguments);
var finalResult = sodMethod.Invoke(null, new object[] { takeResult });
}
}
}
catch (Exception ex)
{
if (ex.InnerException != null && ex.InnerException.InnerException != null && ex.InnerException.InnerException.Message.StartsWith("Invalid column"))
{
MyHelperFunctions.MarkDatabaseForReset();
}
else
throw; //Show error to user - we didn't expect this one
}
有点粗糙,但对我有用。问题范围很广,但应该在 99% 的时间内工作(例如,代码优先数据上下文中的所有属性通常都是数据集)