Hi Paul.
It's not to easy to do that in DO. The main problem that DO do not know how to fill new empty table, but without data it this table DBMS don't allow creation of 1-to-1 FK between Root and ClassNew and ClassNew and ClassA. But you can do that using trick. You can build domain without FKs, fill NewClass table by data and create FKs back. For example, we have two models. First model (which in database now, without changes, old model)
namespace ModelV1
{
[HierarchyRoot]
public abstract class BaseClass : Entity
{
[Field]
[Key]
public int Id { get; set; }
[Field]
public string SomeField { get; set; }
}
public class ClassA : BaseClass
{
[Field]
public string SomeFieldOfClassA { get; set; }
}
public class ClassB : ClassA
{
[Field]
public string SomeFieldOfClassB { get; set; }
}
}
And second model (which has new class in hierarchy, the model we upgrade to)
namespace ModelV2
{
[HierarchyRoot]
public abstract class BaseClass : Entity
{
[Field]
[Key]
public int Id { get; set; }
[Field]
public string SomeField { get; set; }
}
public class NewClass : BaseClass
{
[Field]
public string SomeFieldOfNewClass { get; set; }
}
public class ClassA : NewClass
{
[Field]
public string SomeFieldOfClassA { get; set; }
}
public class ClassB : ClassA
{
[Field]
public string SomeFieldOfClassB { get; set; }
}
}
When i'll write v2.BaseClass class i'll mean BaseClass from ModelV2 namespace.
Now we are building domain without FKs. We using domain configuration like
var configuration = new DomainConfiguration("sqlserver://localhost/DO40-Tests?MultipleActiveResultSets=True");
configuration.Types.Register(typeof (v2.BaseClass));
configuration.Types.Register(typeof (v2.NewClass));
configuration.Types.Register(typeof (v2.ClassA));
configuration.Types.Register(typeof (v2.ClassB));
configuration.ForeignKeyMode = ForeignKeyMode.None;// Switch off FKs
configuration.UpgradeMode = DomainUpgradeMode.PerformSafely;
Now we are creating custom upgrade handler like
public class Upgrader : UpgradeHandler
{
public override bool CanUpgradeFrom(string oldVersion)
{
return true;
}
public override void OnPrepare()
{
using (var connection = new System.Data.SqlClient.SqlConnection("Data Source=localhost;Initial Catalog=DO40-Tests;Integrated Security=True;Persist Security Info=False;MultipleActiveResultSets=True")) {
connection.Open();
using (var command = connection.CreateCommand()) {
command.CommandText =
@"INSERT INTO [DO40-Tests].[dbo].[NewClass] (Id, TypeId)
SELECT Id, TypeId
FROM [DO40-Tests].[dbo].[BaseClass]";
command.ExecuteNonQuery();
}
connection.Close();
}
}
}
This upgrade handler copies data to NewClass table before domain building.
After that we are building domain with domain configuration like
var configuration = base.BuildConfiguration();
configuration.Types.Register(typeof(v2.BaseClass));
configuration.Types.Register(typeof(v2.NewClass));
configuration.Types.Register(typeof(v2.ClassA));
configuration.Types.Register(typeof(v2.ClassB));
configuration.Types.Register(typeof(v2.Upgrader));
configuration.UpgradeMode = DomainUpgradeMode.PerformSafely;
It creates FKs back if data in new table is correct.
That's all. You can build domain in normal mode with configuration
var configuration = new DomainConfiguration("sqlserver://localhost/DO40-Tests?MultipleActiveResultSets=True");
configuration.Types.Register(typeof (v2.BaseClass));
configuration.Types.Register(typeof (v2.NewClass));
configuration.Types.Register(typeof (v2.ClassA));
configuration.Types.Register(typeof (v2.ClassB));
configuration.UpgradeMode = DomainUpgradeMode.PerformSafely;
answered
Nov 14 '14 at 04:56
Alexey Kulakov
772●2●5