I have two entities Users and Addresses. Addresses is an ICollection property on the Users entities. However i am not able to access the individual addresses inside the ICollection. Is that possible and i just have the wrong syntax or does entity framework not allow that.
The Code:
Users:
public partial class User
{
public User()
{
Addresses = new HashSet<Address>();
Comments = new HashSet<Comment>();
Orders = new HashSet<Order>();
Posts = new HashSet<Post>();
}
public long Id { get; set; }
public bool Active { get; set; }
public DateTime? BirthDate { get; set; }
public DateTime Created { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public DateTime? Updated { get; set; }
public string Username { get; set; }
public long? UserTypeId { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<Order> Orders { get; set; }
public virtual ICollection<Post> Posts { get; set; }
public virtual UserType UserType { get; set; }
}
Addresses:
public partial class Address
{
public long Id { get; set; }
public bool Active { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public DateTime Created { get; set; }
public string State { get; set; }
public DateTime? Updated { get; set; }
public long? UserId { get; set; }
public string Zip { get; set; }
public virtual User User { get; set; }
}
Repository (Parent):
public class Repository<T> where T : class
{
private DemoContext _context;
protected DbSet<T> DbSet;
public Repository(DemoContext context)
{
_context =context;
DbSet = _context.Set<T>();
}
public virtual T Get(int Id)
{
// TODO: Implement with return of DbSet.Find();
// DbSet.Find(Id);
return null;
}
public virtual List<T> GetAll()
{
return DbSet.ToList();
}
public virtual void Add(T entity)
{
DbSet.Add(entity);
}
public virtual void Update(T user)
{
_context.Entry<T>(user)
.State = EntityState.Modified;
}
public virtual void SaveChanges()
{
_context.SaveChanges();
}
public virtual void Delete(int Id)
{
// TODO: Implement with return of DbSet.Find();
// DbSet.Remove(Dbset.Find(Id));
}
UserRepository:
public class UserRepository : Repository<User>
{
public UserRepository(DemoContext context)
: base(context)
{
}
public override User Get(int Id)
{
return DbSet
.Where(o => o.Id == Id)
.Include(o => o.Orders)
.Include(o => o.Addresses)
.ToList()
.Single();
}
public override List<User> GetAll()
{
return DbSet
.Include(o => o.Orders)
.Include(o => o.Addresses)
.ToList();
}
public override void Delete(int Id)
{
DbSet.Remove(Get(Id));
}
}
The following code will not give me access to the first address in the ICollection property on the user entity
[HttpGet("[action]")]
public IActionResult Create()
{
var user = userRepository.Get(1);
var order = new Order
{
Address = user.Addresses[0].Address,
City = user.Addresses[0].City,
State = user.Addresses[0].State,
Zip = user.Addresses[0].Zip,
User = user,
SubTotal = 100,
Tax = 25,
Total = 125
};
orderRepository.Add(order);
orderRepository.SaveChanges();
return RedirectToAction("Index");
}
Please advise on how to correct my code so i have access to the entities in the collection.
Just in case anyone was wondering how i solved this here is the answer:
As mentiond by COLD TOLD ICollection does not support array like indexing. However Lists do so change it to a List instead of an ICollection and deleted the hashset that was created in the custructor
public partial class User
{
public User()
{
}
public long Id { get; set; }
public bool Active { get; set; }
public DateTime? BirthDate { get; set; }
public DateTime Created { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public DateTime? Updated { get; set; }
public string Username { get; set; }
public long? UserTypeId { get; set; }
public virtual List<Address> Addresses { get; set; }
public virtual List<Comment> Comments { get; set; }
public virtual List<Order> Orders { get; set; }
public virtual List<Post> Posts { get; set; }
public virtual UserType UserType { get; set; }
}
This allows me to access those nested entities as like this:
[HttpGet("/")]
public IActionResult Create()
{
var user = userRepository.Get(1);
var order = new Order
{
Address = user.Addresses[0].Address1,
City = user.Addresses[0].City,
State = user.Addresses[0].State,
Zip = user.Addresses[0].Zip,
User = user,
SubTotal = 100,
Tax = 25,
Total = 125
};
orderRepository.Add(order);
orderRepository.SaveChanges();
return RedirectToAction("Index");
}
I do not think it a good idea to have that many includes in your select it might cause problems in your performance , you might try to change the order of the query
return DbSet.Include(o => o.Orders)
.Include(o => o.Addresses)
.Where(o => o.Id == Id)
.FirstOrDefault();