C# 自引用对象的实体框架代码第一个错误
我正在尝试将我的第一个EF代码优先对象创建到数据库中。不幸的是,在尝试将对象保存到DB时,出现以下异常: 无法确定从属操作的有效顺序。 依赖关系可能由于外键约束而存在,模型 需求,或存储生成的值 下面是我用来填充数据库的代码: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");
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);