2016-01-20 1 views
1

Я использую Entity Framwork 6.1 (Code First) для игры в аквариум. В этой игре игрока может приобрести AquariumObjects (например, камни, растения, ..), который первым войдет в инвентаре игрока «s (это просто список AquariumObjects в игрока). Оттуда игрок может перетащить AquariumObjects в один из своих аквариумов. Здесь начинаются проблемы: я хотел бы сохранить свойство ForeignKey/Navigation для . Игрок в объект AquariumObject, даже если вы удалите его из списка инвентаря. В моем первом подходе Игрок был даже частью составного ключа AquariumObject. Однако, когда я попытался переместить объект AquariumObject из списка ObjectsInInventory, я получаю эту ошибку на db.SaveChanges(): «Добавление отношения с сущностью, находящейся в состоянии« Удалено », не допускается».EF 6: Можно ли переместить сущность от родителя к дочернему элементу, сохраняя при этом ссылку на родителя в перемещенном объекте?

Таким образом, главная проблема здесь, кажется, что EF удалит объект и обнулять столбец FK в AquariumObject, когда я называю

player.ObjectsInInventory.Remove(dataObject); 

... хотя я пытался вручную восстановить то перед вызовом db.SaveChanges(). Я пытался сделать это по телефону это:

targetAquarium.AquariumObjects.Add(dataObject); 
targetAquarium.Player = ownerPlayer; 
aquariumObject.Player = ownerPlayer; 

В отладчике все выглядит здоровым, хотя, и все ссылки на игрока кажутся нетронутыми.

Когда я выронил ограничение игрока являющегося частью составного ключа в AquariumObject (и просто пытается сохранить его как свойство навигации), я получаю другую ошибку: Отношения не могут быть изменены потому что одно или несколько свойств внешнего ключа не имеют значения NULL. Когда происходит изменение отношения, соответствующее свойство внешнего ключа устанавливается равным нулевому значению. Если внешний ключ не поддерживает нулевые значения, необходимо определить новое отношение, для свойства внешнего ключа должно быть назначено другое ненулевое значение, или не связанный с ним объект должен быть удален

Так что, похоже, невозможно перенести сущность на ребенка, сохраняя при этом ссылку на родителя в перемещенном объекте?

Любые предложения приветствуются! Вот моя текущая модель:

public class Player 
{ 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public Guid PlayerGuid { get; set; } 

    public List<Aquarium> Aquariums { get; set; } 

    public List<AquariumObject> ObjectsInInventory { get; set; } 
} 


public class AquariumObject 
{ 
    [Key] 
    [Column(Order = 0)] 
    [ForeignKey("Player")]  
    public Guid PlayerId { get; set; } 

    public Player Player { get; set; } 


    [Key] 
    [Column(Order = 1)] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int InstanceId { get; set; }  
} 


public class Aquarium 
{ 

    [Key] 
    [Column(Order = 0)] 
    [ForeignKey("Player")] 
    public Guid PlayerGuid { get; set; } 

    public Player Player { get; set; } 

    [Key] 
    [Column(Order = 1)] 
    public int AquariumId { get; set; } 

    public List<AquariumObject> AquariumObjects { get; set; } 
} 

ответ

0

Когда вы делаете player.ObjectsInInventory.Remove(dataObject); вы удаляете AquariumObject из базы данных, поскольку AquariumObject не может существовать без ссылки на Игрок (так как часть первичного ключа). Если вы удалите его из первичного ключа , а также измените его на нулевое поле (по этой причине вы получили вторую ошибку), вы должны убрать его с Player.ObjectsInInventory и добавить в Aquarium.AquariumObjects.

Сказав это, мое предложение было бы упростить модель (проще для меня, по крайней мере :-)) следующим образом. Кроме того, по моему опыту, проще назвать первичные ключи в формате [TableName] Id.EF может найти их без дополнительной настройки (атрибуты ForiegnKey). И, наконец, я считаю, что свойства навигации должны быть помечены как виртуальные:

public class Player 
{ 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public Guid PlayerId { get; set; } 

    public virtual ICollection<Aquarium> Aquariums { get; set; } 

    public virtual ICollection<AquariumObject> AquariumObjects{ get; set; } 
} 

public class AquariumObject 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int AquariumObjectId { get; set; } 

    public int? AquariumId { get; set; } 

    public virtual Aquarium { get; set; } 

    public Guid PlayerId { get; set; } 

    public virtual Player { get; set; } 
} 

public class Aquarium 
{ 
    [Key] 
    [Column(Order = 1)] 
    public int AquariumId { get; set; } 

    public Guid PlayerId { get; set; } 

    public virtual Player Player { get; set; } 

    public virtual ICollection<AquariumObject> AquariumObjects { get; set; } 
} 

Используя эту модель, она изменит концепцию, так что каждый AquariumObject будет приложен к игроку, и, возможно, аквариум. Если он прикреплен к аквариуму, это не будет «в инвентаре», и наоборот, если AquariumId был пустым, это было бы.

Итак, Player.AquariumObjects будет включать в себя все объекты под управлением игроков. Player.AquariumObjects.Where(e => !e.AquariumId.HasValue) будет включать только объекты, находящиеся в инвентаре. И Player.AquariumObjects.Where(e => e.AquariumId == 1) будет включать все в Аквариум с идентификатором 1.

Кроме того, аквариум - это странное слово, если вы говорите (или пишите) достаточно, хе.

+0

Wyatt, спасибо за ваши предложения! Я с радостью вернусь к вашему DataModel, но сначала я постараюсь пометить внешний ключ «Player» в AquariumObject как нулевой, как вы предложили. Я FluentAPI noob, поэтому вот что я пытался, но он по-прежнему помечен как «NOT NULL» в определении таблицы:/Любая идея, что происходит не так? 'modelBuilder.Entity () .HasMany (р => p.AquariumObjectsInInventory) .WithOptional() .HasForeignKey (с => c.PlayerId) .WillCascadeOnDelete (истина);' PS: «аквариум аквариум аквариум!" : D – ponx

+0

@ponx И вы также сделали AquariumObject.PlayerGuid нулевым: 'public Guid? PlayerGuid' или 'public Guid? PlayerId', если вы переименовали его. –

+0

Wyatt, вы спасатель жизни! Я не знал о вопросе как маркер с нулевым значением. Теперь работает! Спасибо огромное! (я бы нажал на вашу репутацию неба, если бы мог) приветствует и снова благодарит, ponx – ponx

Смежные вопросы