C# 自引用对象的实体框架代码第一个错误

C# 自引用对象的实体框架代码第一个错误,c#,entity-framework,ef-code-first,C#,Entity Framework,Ef Code First,我正在尝试将我的第一个EF代码优先对象创建到数据库中。不幸的是,在尝试将对象保存到DB时,出现以下异常: 无法确定从属操作的有效顺序。 依赖关系可能由于外键约束而存在,模型 需求,或存储生成的值 下面是我用来填充数据库的代码: using (var context = new MySample.Context()) { context.Database.CreateIfNotExists(); CloudFile f = new CloudFile(, "file1");

我正在尝试将我的第一个EF代码优先对象创建到数据库中。不幸的是,在尝试将对象保存到DB时,出现以下异常:

无法确定从属操作的有效顺序。 依赖关系可能由于外键约束而存在,模型 需求,或存储生成的值

下面是我用来填充数据库的代码:

using (var context = new MySample.Context())
{
    context.Database.CreateIfNotExists();

    CloudFile f = new CloudFile(, "file1");

    CloudDirectory d = new CloudDirectory(CloudObject.CloudContentType.Customer, "directory1");
    d.Nodes.Add(d);

    FileGroup g = new FileGroup();
    g.CloudObjects.Add(d);

    context.FileGroups.Add(g);
    context.SaveChanges();
}
实际上,我想创建一个
FileGroup
类型的对象。此对象包含文件(
CloudFile
)或目录(
CloudDirectory
)。这些目录可以包含其他目录或文件

以下是上述对象的类:

public class FileGroup {

    public FileGroup()
    {
        CloudObjects = new HashSet<CloudObject>();
    }

    public int FileGroupId { get; set; }

    public string Name { get; set; }

    public virtual ICollection<CloudObject> CloudObjects { get; set; }
}


public abstract class CloudObject {

    public CloudObject(string name)
    {
        Name = name;
    }

    public int CloudObjectId { get; set; }

    public string Name { get; set; }

    public abstract bool hasChildren { get; }

    public int? ParentId { get; set; }

    public virtual Node Parent { get; set; }

    public int? FileGroupId { get; set; }

    public virtual FileGroup FileGroup { get; set; }
}

public class CloudDirectory : CloudObject {

    public CloudDirectory(string name) :base(name)
    {
        Nodes = new HashSet<CloudObject>();
    }

    public override bool hasChildren
    {
        get
        {
            return Nodes.Any();
        }
    }

    public virtual ICollection<CloudObject> Nodes { get; set; }
}

public class CloudFile : CloudObject {

    public CloudFile(string name) : base(name)
    {
    }

    public string ETag { get; set; }

    public override bool hasChildren
    {
        get
        {
            return false;
        }
    }
}
公共类文件组{
公共文件组()
{
CloudObjects=newhashset();
}
public int FileGroupId{get;set;}
公共字符串名称{get;set;}
公共虚拟ICollection CloudObjects{get;set;}
}
公共抽象类CloudObject{
公共CloudObject(字符串名称)
{
名称=名称;
}
public int CloudObjectId{get;set;}
公共字符串名称{get;set;}
公共抽象布尔有子对象{get;}
public int?ParentId{get;set;}
公共虚拟节点父节点{get;set;}
public int?FileGroupId{get;set;}
公共虚拟文件组文件组{get;set;}
}
公共类CloudDirectory:CloudObject{
public CloudDirectory(字符串名称):base(名称)
{
Nodes=newhashset();
}
公立学校有孩子
{
得到
{
返回Nodes.Any();
}
}
公共虚拟ICollection节点{get;set;}
}
公共类CloudFile:CloudObject{
public CloudFile(字符串名称):base(名称)
{
}
公共字符串ETag{get;set;}
公立学校有孩子
{
得到
{
返回false;
}
}
}

你知道我需要在我的对象中更改什么以便成功地存储它们吗?请执行DB?

测试代码中的一些更改(代码注释解释了这些更改):

由于实体之间的关系过于复杂,EF自动约定无法处理它们,因此应在
DbContext
中为它们添加显式映射:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    ...
    modelBuilder.Entity<CloudObject>().HasOptional(x => x.Parent).WithMany(x => x.Nodes).HasForeignKey(x => x.ParentId);
    modelBuilder.Entity<CloudObject>().HasOptional(x => x.FileGroup).WithMany(x => x.CloudObjects).HasForeignKey(x => x.FileGroupId);
}
您的迁移必须看起来像这样:

CreateTable(
    "dbo.CloudObjects",
        c => new
            {
                CloudObjectId = c.Int(nullable: false, identity: true),
                Name = c.String(),
                ParentId = c.Int(),
                FileGroupId = c.Int(),
                ETag = c.String(),
                Discriminator = c.String(nullable: false, maxLength: 128),
            })
        .PrimaryKey(t => t.CloudObjectId)
        .ForeignKey("dbo.FileGroups", t => t.FileGroupId)
        .ForeignKey("dbo.CloudObjects", t => t.ParentId)
        .Index(t => t.ParentId)
        .Index(t => t.FileGroupId);

 CreateTable(
    "dbo.FileGroups",
        c => new
            {
                FileGroupId = c.Int(nullable: false, identity: true),
                Name = c.String(),
            })
        .PrimaryKey(t => t.FileGroupId);

什么是
节点
这里
公共虚拟节点父节点{get;set;}
public abstract class CloudObject
{
    ...
    //public virtual Node Parent { get; set; }
    public virtual CloudDirectory Parent { get; set; }
    ...
}
CreateTable(
    "dbo.CloudObjects",
        c => new
            {
                CloudObjectId = c.Int(nullable: false, identity: true),
                Name = c.String(),
                ParentId = c.Int(),
                FileGroupId = c.Int(),
                ETag = c.String(),
                Discriminator = c.String(nullable: false, maxLength: 128),
            })
        .PrimaryKey(t => t.CloudObjectId)
        .ForeignKey("dbo.FileGroups", t => t.FileGroupId)
        .ForeignKey("dbo.CloudObjects", t => t.ParentId)
        .Index(t => t.ParentId)
        .Index(t => t.FileGroupId);

 CreateTable(
    "dbo.FileGroups",
        c => new
            {
                FileGroupId = c.Int(nullable: false, identity: true),
                Name = c.String(),
            })
        .PrimaryKey(t => t.FileGroupId);