2017-02-01 9 views
1

Я пытаюсь создать первые объекты первого кода EF в базе данных. К сожалению при попытке сохранить мои объекты в БД я получаю это исключение:Первая ошибка кода Entity Framework с объектами саморегуляции

Невозможно определить действительный заказ на зависимые операции. Зависимости могут существовать из-за ограничений внешнего ключа, для моделей или для хранения значений.

Вот код, который я использую для заполнения БД:

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' здесь публичный виртуальный узел Parent {получить; задавать; } '? –

ответ

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 автоматических конвенций для борьбы с ними, вы должны добавить явные отображения для них в вашем 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); 
} 

Примечание: Я предположил, что здесь FileGroup не является обязательным для данного CloudObject. Если это необходимо, вы должны изменить метод HasOptional на HasRequired.

Вы должны также изменить тип этого свойства:

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