我想从与大多数提出的策略不同的方向来探讨NHibernate中的数据库版本控制和自动化升级。
因为每个对象都是由XML映射定义的,所以我想获取每个映射文件/配置的大小和校验和,并将其与可能的自定义更新脚本一起存储在文档数据库(raven或其他东西)中。如果找不到脚本,请使用NHibernate DDL生成器更新对象架构。通过这种方式,我可以检测到更改,如果除了DDL之外还需要进行DML更改,或者执行仔细排序的转换,理论上我可以以一种受控的、可测试的方式来完成。这也应该保持一定程度的持久层不可知论,尽管我认为脚本仍然必须是特定于数据库系统的。
诀窍是,从数据库生成“旧的”映射文件,并将它们与当前的映射文件进行比较。我不知道这是否可能。我也不知道我是否还遗漏了什么东西,这会使这个策略变得非常不切实际。
那么,我的问题是:这种策略有多实际,为什么?
发布于 2012-07-12 17:21:36
我为解决这个问题所做的一切
从名为SchemaVersion
<代码>G213
为了生成脚本,我使用了两个选项
的表和代码。
更新:
“您使用什么方法存储当前版本”
小示例
像这样的东西
public static class Constants
{
public static readonly Version DatabaseSchemaVersion = new Version(1, 2, 3, 4);
}
public class DBMigration
{
private IDictionary<Version, Action> _updates = new Dictionary<Version, Action>();
private Configuration _config;
private Dialect _dialect;
private IList<Action<ISession>> _actions = new List<Action<ISession>>(16);
private string _defaultCatalog;
private string _defaultSchema;
private void CreateTable(string name, Action<Table> configuretable)
{
var table = new Table(name);
configuretable(table);
string createTable = table.SqlCreateString(_dialect, _config.BuildMapping(), _defaultCatalog, _defaultSchema);
_actions.Add(session => session.CreateSQLQuery(createTable).ExecuteUpdate());
}
private void UpdateVersionTo(Version version)
{
_actions.Add(session => { session.Get<SchemaVersion>(1).Value = version; session.Flush(); });
}
private void WithSession(Action<session> action)
{
_actions.Add(action);
}
public void Execute(Configuration config)
{
_actions.Clear();
_defaultCatalog = config.Properties[NH.Environment.DefaultCatalog];
_defaultSchema = config.Properties[NH.Environment.DefaultSchema];
_config = config;
_dialect = Dialect.GetDialect(config.Properties);
using (var sf = _config.BuildSessionFactory())
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
Version dbVersion = session.Get<SchemaVersion>(1).Value;
while (dbVersion < Constants.DatabaseSchemaVersion)
{
_actions.Clear();
_updates[dbVersion].Invoke(); // init migration, TODO: error handling
foreach (var action in _actions)
{
action.Invoke(session);
}
tx.Commit();
session.Clear();
dbVersion = session.Get<SchemaVersion>(1).Value;
}
}
}
public DBMigration()
{
_updates.Add(new Version(1, 0, 0, 0), UpdateFromVersion1);
_updates.Add(new Version(1, 0, 1, 0), UpdateFromVersion1);
...
}
private void UpdateFromVersion1()
{
AddTable("Users", table => table.AddColumn(...));
WithSession(session => session.CreateSqlQuery("INSERT INTO ..."));
UpdateVersionTo(new Version(1,0,1,0));
}
...
}https://stackoverflow.com/questions/11434351
复制相似问题