ServiceStack Ormlite:parent 和 child 表之间的循环引用阻止创建外键

ServiceStack Ormlite: Circular reference between parent and child tables prevents foreign key creation

我们正在试验从 EF6 到 ServiceStack.OrmLite 的转换,并且在 table 创建期间遇到问题 Parent table 包含对 a 的引用(default/active)Childtable。我们有一个 1:many Parent:Child 关系,其中 Parent 有一个对特定 child 的附加可选引用。生成的数据库 table 将各自包含彼此的外键,例如

Parent table:
Id  (int)   | Name (varchar)    | ActiveChildId (int null FK)

Child table:
Id  (int)   | Description (varchar) | ParentId (int FK)

我们正在尝试模仿 EF 提供的导航 属性 功能,但不确定这是否可行?

例如,如果我们声明如下类,其中

public class Parent
{
    public int Id {get;set;}
    public string Name {get;set;}

    // the item currently published, modelled like an EF navigation property
    [Reference]
    public Child ActiveChild {get;set;}     

    [References(typeof(Child))]
    public int? ActiveChildId { get; set; }

    // all items mapped to this Parent
    [Reference]
    public List<Child> AllChildren {get;set;}   
}

public class Child
{
    public int Id {get;set;}
    public string Description {get;set;}

    [References(typeof(Parent))]
    public int ParentId {get;set;}

    [Reference]
    public Parent MyParent {get;set;}
}

现在,当我们使用Ormlite table创作时,如:

using (var db = DbFactory.Open())
{
    db.CreateTableIfNotExists<Parent>();
    db.CreateTableIfNotExists<Child>();
}

我们收到如下错误:

System.Data.SqlClient.SqlException (0x80131904): Foreign key 'FK_Parent_Child_ActiveChildId' references invalid table 'Child'.
Could not create constraint or index. See previous errors.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
[etc etc]

基本上,似乎创建 Parent table 失败了,因为 Child table 尚不存在,因此无法创建外键,类似地反转table 创建顺序失败,因为没有 Parent 就无法创建 Child?

我们是否能够在 OrmLite 中以这种方式对我们的 类 进行建模,或者如果不能,那么捕获这种关系的 suggested/recommended 结构是什么?

谢谢

OrmLite 是代码优先的 ORM,它的 POCO 是底层 table 的 1:1 映射。您不能在 OrmLite 中定义这样的循环关系,因为您不能在 SQL 中定义这样的循环关系,而不求助于多步骤 table 创建,其中毕竟添加了外键约束 table 已创建。我建议不要使用循环外键定义 tables,您可以随时在创建 tables 之后添加它们。

使用 [References(Type)] 属性创建一个外键,但这对于 OrmLite POCO References 不是必需的,它可以使用隐式命名约定来定义隐式关系,例如:

public class Parent
{
    [AutoIncrement]
    public int Id { get; set; }

    public string Name { get; set; }

    [Reference]
    public Child ActiveChild { get; set; }

    public int? ActiveChildId { get; set; }

    [Reference]
    public List<Child> AllChildren { get; set; }
}

public class Child
{
    [AutoIncrement]
    public int Id { get; set; }

    public int ParentId { get; set; }

    public string Description { get; set; }
}

然后您可以正常创建和使用:

db.DropAndCreateTable<Parent>();
db.DropAndCreateTable<Child>();

var parent = new Parent
{
    Name = "Parent",
    ActiveChild = new Child {  Description = "Active" },
    AllChildren = new List<Child>
    {
        new Child { Description = "Child 1" },
        new Child { Description = "Child 2" },
    }
};

db.Save(parent, references:true);

var dbParent = db.LoadSelect<Parent>();
dbParent.PrintDump();