2017-02-01 12 views
1

最初のEFコードの最初のオブジェクトをデータベースに作成しようとしています。残念ながら、私のオブジェクトをDBに保存しようとすると、例外が発生します。エンティティフレームワーク自己参照オブジェクトの最初のエラーコード

従属操作の有効な順序を判断できません。 外部キー制約、モデル 要件、またはストア生成値のために依存関係が存在する可能性があります。ここで

私は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; 
     } 
    } 
} 

は、私は、彼らが成功したDBを行う保存することができるように、私のオブジェクトに変更する必要があるか任意のアイデア?テストコードで

+0

Node'ここで 'パブリック仮想ノードの親が{取得'何ですが。セット; } '? –

答えて

1

いくつかの変更(コードのコメントは、それらを説明):

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

    CloudFile f = new CloudFile("file1"); 

    CloudDirectory d = new CloudDirectory("directory1"); 

    //This seems to be wrong: 
    //d.Nodes.Add(d); 
    d.Nodes.Add(f); //I guess you don't want d to be its own parent, but want it to be f's parent 

    FileGroup g = new FileGroup(); 
    g.CloudObjects.Add(d); 
    //Another way to do it: 
    //d.FileGroup = g; 

    //You also want f to be in the FileGroup, you have to add it explicitly 
    g.CloudObjects.Add(f); 
    //Another way to do it: 
    //f.FileGroup = g; 

    context.FileGroups.Add(g); 
    context.SaveChanges(); 
} 

エンティティ間の関係は、EF自動規則は、それらに対処するのは少し複雑すぎるとして、明示的なマッピングを追加する必要があります

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); 
} 

注:お使いのDbContextで彼らのために私はFileGroupが与えられたCloudObjectに必須ではないことを仮定する。必須の場合は、方法HasOptionalHasRequiredに変更する必要があります。

また、このプロパティのタイプに変更する必要があります

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);