简体   繁体   中英

Retrieving data from multiple tables using Entity Framework

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'

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.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM