In my multiplayer game the player has many items in their inventory. Some of which are block items. Block items in the player's inventory can also be assigned to "slots" (for a quick slot system in the game).
The way I have the entity classes is as follows: I have an entity of type PlayerContext
that has an Inventory
entity. The Inventory
entity extends the ItemContainer
entity which has many ItemContext
entities. The BlockItem
entity extends the ItemContext
entity. The PlayerContext
also has "slots" that are a foreign key reference to BlockItem
entities.
I encounter a problem when I am changing the "slots". I can assign a BlockItem
to a slot and that is saved in the database. However I can't remove a BlockItem
from a slot. I am trying to do this by setting the slot = null
and then updating the PlayerContext
. The newly assigned BlockItem
is saved as a foreign key but the slot that I am trying to clear is not saved and still has the reference to the BlockItem
.
In code this looks like:
class ChunkContext : DbContext
{
...
public DbSet<PlayerContext> Players { get; set; }
public DbSet<ItemContext> Items { get; set; }
public DbSet<BlockItem> blockItems { get; set; }
public DbSet<ItemContainerContext> ItemContainers { get; set; }
public DbSet<Inventory> Inventories { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseSqlite("Data Source=../chunks.db");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
...
modelBuilder.Entity<PlayerContext>().HasOne(p => p.inventory);
modelBuilder.Entity<ItemContext>().HasKey(i => i.id);
modelBuilder.Entity<ItemContext>().HasOne(i => i.container).WithMany(ic => ic.items);
...
modelBuilder.Entity<ItemContainerContext>().HasKey(ic => ic.id);
modelBuilder.Entity<ItemContainerContext>().HasMany(ic => ic.items).WithOne(item => item.container);
base.OnModelCreating(modelBuilder);
}
...
}
[Index(nameof(username), IsUnique = true)]
public class PlayerContext
{
public PlayerContext() { }
[Key]
public int id { get; set; }
...
[Required]
public Inventory inventory { get; set; }
// resource slots. this is digusting and I'm sorry
public BlockItem slot0 { get; set; }
public BlockItem slot1 { get; set; }
public BlockItem slot2 { get; set; }
public BlockItem slot3 { get; set; }
public BlockItem slot4 { get; set; }
public BlockItem slot5 { get; set; }
public BlockItem slot6 { get; set; }
public BlockItem slot7 { get; set; }
internal void SetResourceSelectorSlot(int slotIndex, int itemId)
{
using (var db = new ChunkContext())
{
if (slotIndex == 0) slot0 = inventory.FindItem(itemId) as BlockItem;
else if (slot0 != null && slot0.id == itemId) slot0 = null;
if (slotIndex == 1) slot1 = inventory.FindItem(itemId) as BlockItem;
else if (slot1 != null && slot1.id == itemId) slot1 = null;
if (slotIndex == 2) slot2 = inventory.FindItem(itemId) as BlockItem;
else if (slot2 != null && slot2.id == itemId) slot2 = null;
if (slotIndex == 3) slot3 = inventory.FindItem(itemId) as BlockItem;
else if (slot3 != null && slot3.id == itemId) slot3 = null;
if (slotIndex == 4) slot4 = inventory.FindItem(itemId) as BlockItem;
else if (slot4 != null && slot4.id == itemId) slot4 = null;
if (slotIndex == 5) slot5 = inventory.FindItem(itemId) as BlockItem;
else if (slot5 != null && slot5.id == itemId) slot5 = null;
if (slotIndex == 6) slot6 = inventory.FindItem(itemId) as BlockItem;
else if (slot6 != null && slot6.id == itemId) slot6 = null;
if (slotIndex == 7) slot7 = inventory.FindItem(itemId) as BlockItem;
else if (slot7 != null && slot7.id == itemId) slot7 = null;
db.Players.Update(this);
db.SaveChanges();
}
}
}
public class ItemContext
{
[Key]
public int id { get; set; }
public ItemContainerContext container { get; set; }
...
}
public class BlockItem : ItemContext
{
...
}
The SetResourceSelectorSlot
is successfully setting and saving the foreign key reference to the items. But it is not clearing the field when I set it to null. When I set it to null it's not changed in the database at all. I don't want to delete the BlockItem
that it references (because it's still in the player's inventory). I just want the field to be set to NULL in the database. The field is nullable and it's null by default. But nothing I do can change it back to being null after it has been set. Also I am setting the field to be null and can confirm that when debugging. But that change is not propagated to the DB.
Adding this line:
db.Entry(this).Reference(p => p.slot0).IsModified = true;
after I set the field to null makes sure it is saved in the database.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.