How to use Linking Table in Entity Framework - c#

I've been trying to puzzle out how to use entity framework to return a query like so
{
UserID: 1,
Roles: ["RoleOne","RoleTwo","RoleThree"]
}
Where my tables are as such:
public class User
{
public int? ID { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
}
public class UserRoles
{
public int ID { get; set; }
public int UserID{ get; set; }
public int RoleID { get; set; }
}
public class Roles
{
public int ID { get; set; }
public string? Name { get; set; }
}
I've tried joins, and looked into creating a relationship in the classes, as well as trying to figure out groupBy, but all with no luck.
If I'm missing something obvious please let me know! Thanks!

Your response model should be like this:
public class RespModel
{
public int UserID { get; set; }
public List<string> Roles { get; set; }
}
And your query could be like this:
var query = from userRolesRec in _context.UserRoles
join user in _context.User on userRolesRec.UserID equals user.ID ?? 0
select new RespModel
{
UserID = user.ID,
Roles = (from roles in _context.Roles
where userRolesRec.RoleID == roles.ID
select roles.Name).ToList()
}

Related

How to perform a simple query on a join table when the join table is created by EF?

Say I have two entities with a many-to-many relationship and create the join table manually:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<UserPermission> UserPermissions { get; set; }
}
public class Permission
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<UserPermission> UserPermissions { get; set; }
}
public class UserPermission
{
public int UserId { get; set; }
public User User { get; set; }
public int PermissionId { get; set; }
public Permission Permission { get; set; }
}
If I want to find out if a user has a specific permission I can run a simple query like this
var query = _context.UserPermissions
.Where(up => up.UserId == userId && up.PermissionId == permissionId);
Now say I remove the join table and let entity framework create it for me:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Permission> Permissions { get; set; }
}
public class Permission
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<User> Users { get; set; }
}
How can I perform this same simple query on the db without pulling in a load of unnecessary data or overcomplicating the query?
The EF will create UserPermissions for you. Please find at the following LINK

How do I convert this SQL to Linq? [duplicate]

This question already has an answer here:
SQL to LINQ with multiple join, count and left join
(1 answer)
Closed 2 years ago.
What would this SQL look like in Linq?
You can see the SQL statement that I want to use, I am pretty new to Linq:
SELECT user_id
FROM profiles
LEFT JOIN interests ON profiles.id = interests.profile_id
WHERE interest IN ('Shopping', 'Art')
AND Sex IN ('Man', 'Woman')
AND user_id NOT IN (SELECT user_1 FROM matches)
AND user_id != 84
GROUP BY user_id
ORDER BY COUNT(user_id) DESC;
Beneath you can see the different models, All the models have an id from modelbase
Profile model:
namespace Sparks.Presentation.Entities
{
public partial class Profile: ModelBase
{
public Profile()
{
Interests = new HashSet<Interest>();
}
public int UserId { get; set; }
public string Name { get; set; }
public string Picture { get; set; }
public string Birthdate { get; set; }
public string Sex { get; set; }
public string Orientation { get; set; }
public virtual User User { get; set; }
public virtual ICollection<Interest> Interests { get; set; }
[NotMapped]
public IFormFile FormFile { set; get; }
}
}
Interest model:
namespace Sparks.Presentation.Entities
{
public partial class Interest: ModelBase
{
public int ProfileId { get; set; }
public string InterestName { get; set; }
public virtual Profile Profile { get; set; }
}
}
Matchmodel:
namespace Sparks.Presentation.Entities
{
public partial class Match: ModelBase
{
public Match()
{
Chats = new HashSet<Chat>();
}
public int User1 { get; set; }
public int User2 { get; set; }
public bool Matchstatus { get; set; }
public bool Matchmade { get; set; }
public DateTime CreatedOn { get; set; }
public virtual User User1Navigation { get; set; }
public virtual User User2Navigation { get; set; }
public virtual ICollection<Chat> Chats { get; set; }
}
}
Hope someone can help me out?
This is closer to the query what is expected. Looks similar as SQL but select part is last statement.
var interestFilter = new [] {"Shopping", "Art"};
var sexFilter = new [] {"Man", "Woman"};
var query =
from p in ctx.Profiles
from i in p.Interests
where interestFilter.Contains(i.InterestName) && sexFilter.Contains(p.Sex)
&& !ctx.Matches.Any(m => m.User1 == u.UserId)
&& p.UserId != 84
group p by p.UserId into g
order by g.Count()
select g.Key;
var result = query.ToList();

Entity Framework Populating Child Objects using Foreign Key

I hope this isn't a duplicate as I have been looking but I was looking more at the reasoning behind this.
I have set up a user object.
public class User
{
public User()
{
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserID { get; set; }
public Guid UserGuid { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public int CompanyID { get; set; }
public int StatusID { get; set; }
[ForeignKey("StatusID")]
public Status Status { get; set; }
public int RoleID { get; set; }
[ForeignKey("RoleID")]
public UserRole UserRole { get; set; }
}
And the Child Objects
public class UserRole
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int RoleId { get; set; }
public string Role { get; set; }
}
public class Status
{
[Key]
public int StatusId { get; set; }
public string Description { get; set; }
}
When I call
var testuser = dbContext.User.Where(u => u.CompanyID == 1).FirstOrDefault();
I get users.Status as being null, but users.StatusID = 1.
however, if I call
var status = dbContext.Status.ToList();
var role = dbContext.UserRole.ToList();
var testuser = dbContext.User.Where(u => u.CompanyID == 1).FirstOrDefault();
then call testuser.Status, I can see the correct object related to StatusId of 1.
Can someone explain why this would solve the issue and also how I can make it work without having to call the following beforehand.
var status = dbContext.Status.ToList();
Thanks
You can try as shown below.
Note : Use Eager loading with Include()
Eager loading is the process whereby a query for one type of entity
also loads related entities as part of the query
using System.Data.Entity;
var testuser = dbContext.User.Where(u => u.CompanyID == 1)
.Include(p => p.Status)
.FirstOrDefault();
Just use your property like this. Keyword virtual put its property to lazy loading and then you can access the whole object.
public virtual Status Status { get; set; }
And BTW, I edited your class. There are un-needed things, because you can access StatusID by property Status (like int statID = Status.StatusID;) and same to UserRole.
public class User
{
public User()
{
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserID { get; set; }
public Guid UserGuid { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public int CompanyID { get; set; }
public virtual Status Status { get; set; }
public virtual UserRole UserRole { get; set; }
}
}

ASP.NET MVC model from db

I created my model from DB in which I have tables Users, Roles and UsersInRoles which is an intermediary table between the first 2.
My question is how do I take specific users where Roles = something since the table UsersInRoles is not added to the model?
public partial class Role
{
public Role()
{
this.Users = new HashSet<User>();
}
public int RoleID { get; set; }
public string RoleName { get; set; }
public string RoleDescription { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public partial class User
{
public User()
{
this.Roles = new HashSet<Role>();
}
public int UserID { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
public ActionResult Index()
{
var users = db.Users;
return View(users.ToList());
}
I believe this will work...
var usersInRole = db.Users.Where(x => x.Roles.Any(y => y.RoleId == roleid));
I admittedly haven't had much experience with HashSets, but is there any reason a simple Linq query wouldn't work?
var requestedUsers = from UsersInRoles
in db.Users
where UsersInRoles.Roles.Contains(DesiredRoleHere)
select UsersInRoles;

EF5: how to select entity with it's child entities with raw SQL

For the purpouse of the application that I developing I need to select entities which have navigation properties to another entities with native sql query.
This is my entity classes:
public class UserModel
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public int? CodeId { get; set; }
public CodeModel Code { get; set; }
}
public class CodeModel
{
public int CodeId { get; set; }
public int Code { get; set; }
public int UserId { get; set; }
}
My SQL query is:
string sql = "SELECT u.* FROM UserModel AS u" +
"INNER JOIN CodeModel AS c" +
"ON c.UserId = u.UserId";
and the my C# method is:
public IEnumerable<UserModel> GetUsers()
{
var users = dbContext.UserModel.SqlQuery(sql);
return users;
}
In result I get the users but the navigation property for Code on UserModel class is null. How to do this task with native query? I know how to do it with LINQ.

Categories

Resources