Reputation: 3
I want to get data from multiple tables based on the itemId
of each table.
Currently I have an item table with an ItemId
column that has a 1:m relationship with another tables called ExplicitMods
:
namespace Poe.Models
{
public class Item
{
[Key]
public string ItemId { get; set; }
public List<ExplicitMod> ExplicitMods { get; set; }
}
}
namespace Poe.Models
{
public class ExplicitMod
{
public ExplicitMod(string Name)
{
this.Name = Name;
}
[Key]
public string ItemId { get; set; }
public string Name { get; set; }
}
}
I also have a context with both tables set up:
namespace Poe.DataAccess
{
public class DatabaseContext : DbContext
{
public DbSet<Item> Items { get; set; }
public DbSet<ExplicitMod> ExplicitMod { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
}
}
}
I then try to call the item tables, search on a random name called "Brood Star", and join the explicitMod table:
public static void Search()
{
//return FindItems(i);
using (var db = new DatabaseContext())
{
var blogs = db.Items
.Where(b => b.Name.Equals("Brood Star"))
.Include(es => es.ExplicitMods).ToList();
Debug.Write(blogs);
}
}
What should I do to get the result as one table?
I also get this error:
System.Data.SqlClient.SqlException: 'Invalid object name 'ExplicitMod'
Upvotes: 0
Views: 70
Reputation: 34653
Your references need a bit of adjustment. For a 1-many, your ExplicitMod will need it's own PK, and a FK to Item:
public class ExplicitMod
{
public ExplicitMod()
{}
public ExplicitMod(string name)
{
Name = name;
}
[Key]
public string ExplicitModId { get; set; }
[ForeignKey("Item")]
public string ItemId{ get; set; }
public string Name { get; set; }
public virtual Item Item { get; set; }
}
I believe it also will need a parameterless constructor for EF to be able to construct these on the fly. You may be able to get away with a protected or private constructor.
For Item:
public class Item
{
[Key]
public string ItemId { get; set; }
public virtual ICollection<ExplicitMod> ExplicitMods { get; private set; } = new List<ExplicitMod>();
}
Initializing the collection and using a private setter is recommended to save steps when creating new entities to populate, and having external code setting a collection reference to a new, untracked set of entities. (For unit testing, I typically mark the setter internal to allow unit tests to set up stubs)
I'd strongly recommend using an int
or Guid
for the PK/FK fields rather than strings. If you want to have unique identifying strings then add these as additional columns /w unique constraints. Using numeric or UUID keys are a form of "meaningless keys" which save indexing space and make modifying values easier without worrying about changing/invalidating data relationships accidentally.
Upvotes: 1