EF delete a reference in bridge table - asp.net-mvc

I have 2 entities Group and User. 1 'Group' has a collection of users and 1 'User' has a collection of groups. I want to delete a record in the bridge table
Group: GroupID, name
User: UserID, name
GroupUser (bridge table): GroupID, UserID
currently I have
var query = from u in context.User
from g in u.Group
where u.UserID==1 && g.GroupID==10
But then how do I delete the record in the bridge table with the matching UserID and GroupID. query.Clear() returns error
Edit: in my EF, there is no object to represent the bridge table. so I cannot user context.UserGroup(...) should I create an object for the bridge table? Or is there any other way to solve this problem?

Assuming your bridge table is named UserGroup(s)
var group = context.UserGroup.SingleOrDefault(x => x.UserID == 1 && x.GroupID == 10);
if (group != null)
{
context.DeleteObject(group);
context.SaveChanges();
}
else
//Do something in response

You should select from your bridge table:
var results = from bt in context.BridgeTable
where bt.UserID = 1 and bt.GroupID = 1
foreach(var result in results)
{
context.DeleteObject(result);
}
context.SaveChanges();

Related

Joining the Resource Table and the Resources_Role Table in a Repository using Linq query

How do I join the Resources Table to the Resources_role table where resources_id column is common in both table. Below is my code to fetch the Resources table using the Role_id, however I want all the records from the resources table that share the same resources_id column with the Resources_Role to be fetched.
How do I do this join please, below is my code
public IQueryable <Resources_Role> FindResourceByRoleID(int RoleId)
{
var roleid = from p in context.Resources_Role
select p;
roleid = roleid.Where(p => p.ROLE_ID==(RoleId));
return roleid;
}
The thing you should watch is the method return type. Depending on what you want to return, you should adjust the return type based on result set from JOIN query you're using:
// returning resources
public IQueryable<Resources> FindResourceByRoleID(int RoleId)
{
return (from res in context.Resources
join role in context.Resources_Role
on res.resources_id equals role.resources_id
where res.ROLE_ID == RoleId
select res);
}
// returning resource role
public IQueryable<Resources_Role> FindResourceRoleByRoleID(int RoleId)
{
return (from role in context.Resources_Role
join res in context.Resources
on role.resources_id equals res.resources_id
where res.ROLE_ID == RoleId
select role);
}
Those queries above will produce SQL statements as shown below:
-- returns resources
SELECT t0.* FROM Resources AS t0 INNER JOIN Resources_Role AS t1
ON t0.resources_id = t1.resources_id
WHERE t0.ROLE_ID = #RoleId
-- returns resources role
SELECT t0.* FROM Resources_Role AS t0 INNER JOIN Resources AS t1
ON t0.resources_id = t1.resources_id
WHERE t1.ROLE_ID = #RoleId
Note: Cannot implicitly convert type System.Linq.IQueryable<Resource> to System.Linq.IQueryable<Resources_Role> is self-explanatory: it occurs because your query returns IQueryable<Resource> but the method return type set to IQueryable<Resources_Role>. You must adjust the query to return IQueryable<Resources_Role> instead.
After you've got your roleId from your method, you could do something like the following to return a Resource:
var resources = from resource in context.Resources
where resource.ROLE_ID == roleId
join resource_role in context.Resources_Role
on resource.resources_id equals resource_role.resource_id
select resource;
To get a Resource_Role you could do something like this:
var resource_role = from role in context.Resource_Roles
join resource in context.Resources_Role.Where(resource_role => resource_role.ROLE_ID == roleId)
on role.resources_id equals resource.resource_id
select role;
I'm afraid I don't have a working MVC env to test any of this in atm, but it should be a good starting point.

Get value of each comma separated ID from another table in Web Api-not working in live

I have a 'Skill' table where i store skills. And in 'Job' table i store all required skill when post job like UpWork. Employeers have checkbox to select all required skills. But i store skillID like: 1,5,6,8 in job table. When i retrieve the job details, i want to get name of the all skills because i want to show SkillName with other details of the Job from job table. My Web Api:
[HttpGet]
[Route("api/JobApi/BrowseJobs/")]
public object BrowseJobs()
{
var skills = db.Skills.ToDictionary(d => d.SkillID, n => n.SkillName);
var jobData = (from j in db.Jobs where j.Preference==2
//from cj in j.ClosedJobs.DefaultIfEmpty()
join cj in db.ClosedJobs.DefaultIfEmpty()
on j.JobID equals cj.JobID into closedJob
where !closedJob.Any()
join c in db.Categories on j.Category equals c.CategoryID
join jobContract in
(
from appliedJob in db.AppliedJobs.DefaultIfEmpty()
from offer in appliedJob.JobOffers.DefaultIfEmpty()
from contract in db.Contracts.DefaultIfEmpty()
select new { appliedJob, offer, contract }
).DefaultIfEmpty()
on j.JobID equals jobContract.appliedJob.JobID into jobContracts
where !jobContracts.Any(jobContract => jobContract.contract.CompletedDate != null)
select new
{
JobTitle = j.JobTitle,
JobID = j.JobID,
ReqSkillCommaSeperated = j.ReqSkill,
Category = c.CategoryName,
Budget=j.Budget,
Deadline=j.Deadline,
JobDetails=j.JobDetails,
PublishDate=j.PublishDate,
TotalApplied=(from ap in db.AppliedJobs where j.JobID == ap.JobID select ap.AppliedJobID).DefaultIfEmpty().Count()
}).AsEnumerable()
.Select(x => new
{
JobID = x.JobID,
JobTitle = x.JobTitle,
Category = x.Category,
Budget = x.Budget,
Deadline = x.Deadline,
JobDetails = x.JobDetails,
PublishDate = x.PublishDate,
SkillNames = GetSkillName(x.ReqSkillCommaSeperated, skills),
TotalApplied = (from ap in db.AppliedJobs where x.JobID == ap.JobID select ap.AppliedJobID).DefaultIfEmpty().Count()
}).ToList();
return jobData.AsEnumerable();
}
private string GetSkillName(string reqSkill, Dictionary<int, string> skills)
{
if (reqSkill == null) return string.Empty;
var skillArr = reqSkill.Split(',');
var skillNameList = skillArr.Select(skillId => skills[Convert.ToInt32(skillId)])
.ToList();
return String.Join(",", skillNameList);
}
My Problem is that the code is working well in my VS 2013. But when i uploaded it on a Godaddy live server, it doesn't work! returns 500 internal server error
Now i want to Make a SQL query instead of Linq. Can i do SQL with my desired result?
===================Edited=====================
your sql code is well worked. But i have others condition to be put on.
1. I need to show those job which is not closed yet (ClosedJobs table take the closed jobs ID).If a job ID is found on ClosedJobs table, it will not return in the list.
join cj in db.ClosedJobs.DefaultIfEmpty()
on j.JobID equals cj.JobID into closedJob
where !closedJob.Any()
Those job which is not found on Contracts table(Contracts table take the jobID of a job that is started as contract)
2nd Edit===================
join jobContract in
(
from appliedJob in db.AppliedJobs.DefaultIfEmpty()
from offer in appliedJob.JobOffers.DefaultIfEmpty()
from contract in db.Contracts.DefaultIfEmpty()
select new { appliedJob, offer, contract }
).DefaultIfEmpty()
on j.JobID equals jobContract.appliedJob.JobID into jobContracts
where !jobContracts.Any(jobContract => jobContract.contract.CompletedDate != null)
EXP: Job table has relation with AppliedJobs table. AppliedJobs table has relation with JobOffers. JobOffers has relation with Contracts.
i don't want to show those jobs that are completed.(Contracts.CompletedDate != null). When a contract starts the field CompletedDate is set to null. After completing the contract ,it is changed null to the completed date.
Where i will apply the condition?
How can i do that? Can you help me? #John Cappelletti
EDIT - Removed OUTER APPLY
Below is a simple example of using Stuff() and XML. If the sequence is important, then we must split the string first.
To be clear #Skills and #YourData are table variables and simply demonstrative.
Example
Declare #Skills table (SkillID int,SkillName varchar(50))
Insert Into #Skills values
(1,'ASP')
,(2,'JavaScript')
,(3,'AngularJS')
,(4,'WordPress')
,(5,'Joomla')
Declare #YourData table (ID int,ReqSkill varchar(50))
Insert Into #YourData values
(1,'2,3,4,5,1')
,(2,'3')
,(3,'3,4,5,2')
,(4,null)
Select A.ID
,Skills = Stuff((Select ',' +SkillName
From #Skills
Where charindex(concat(',',SkillID,','),','+A.ReqSkill+',')>0
For XML Path ('')),1,1,'')
From #YourData A
-- Your WHERE Statement Here --
Returns
ID Skills
1 ASP,JavaScript,AngularJS,WordPress,Joomla
2 AngularJS
3 JavaScript,AngularJS,WordPress,Joomla
4 NULL

Return table records based on user role / table Join failing - linq query

I am building a MVC 5 (EF6) application that has a photographer table that's linked to the users table.
I identify a photographer by setting a role on the user account. The photographer table holds additional information not table. I have different types of users accessing the system.
I need to get the photographer table records based on the user being in the photographer role. I have the following solution but it comes back with the following error message when i try to access query result.
Unable to create a constant value of type 'Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole'. Only primitive types or enumeration types are supported in this context.
var photogpraherRole = db.Roles.Single(r => r.Name == "photographer");
var users = photogpraherRole.Users.ToList();
var photographersList =
from photographer in db.Photographers
join user in users on photographer.User.Id equals user.UserId
orderby photographer.Priority
select photographer;
foreach (var photographer in photographersList)
{
var photographerName = photographer.User.FirstName;
}
After some research and the help from #Shawn Yan, this is the solution i came up with.
var photographerRole = db.Roles.SingleOrDefault(m => m.Name == "photographer");
var disabledRole = db.Roles.SingleOrDefault(m => m.Name == "disabled");
var users = db.Users.Where(m => m.Roles.All(r => r.RoleId == photographerRole.Id && r.RoleId != disabledRole.Id)).ToList();
var photographersList =
from photographer in db.Photographers.ToList()
join user in users on photographer.User.Id equals user.Id
where photographer.Location == booking.location.Location
orderby photographer.Priority
select photographer;
var photographers = photographersList.ToList();

Entity Framework - How can I check whether an object is under another object's Hierarchy?

I have an table called Contents. There's one to many relationship on Contents, so each content can have a parent and children. I'm using EF Code First, so I have an entity Content which has Id, ParentId, Parent and Children properties.
Now, I'm building an ajax based tree of Contents. I have a simple action that returns a JSON of one level of Contents, based on parentId:
public JsonResult GetContents(int? parentId = null)
{
return Json(db.Contents
.Where(p => p.ParentId == parentId)
.Select(p => new
{
id = p.Id,
name = p.Name
});
}
The next thing I want to do is to automatically select some value. The problem is that the value can be deep inside the hierarchy of the tree, so for each content I'll need to know whether or not the selected value is a child or grandchild and so forth, of it.
public JsonResult GetContents(int? parentId = null, int selectedValue)
{
return Json(db.Contents
.Where(p => p.ParentId == parentId)
.Select(p => new
{
id = p.Id,
name = p.Name
isSelectedValueUnderThisHierarchy: // How can I efficiently implement this?
});
}
It's easy to implement with a lot of queries, but I'm trying to make things as efficient as possible, and EF doesn't provide any Recursive methods as far as I know, so I really have no clue where to start.
You could first build a list of all the ParentIds from the selected value. Depending on the size of your Contents table, you could first load the data, then loop through without making extra queries to the database.
db.Contents.Load();
var selectedItem = db.Contents.Find(selectedValue);
var parents = new List<int>();
while (selectedItem.ParentId != null)
{
parents.Add(selectedItem.ParentId.Value);
selectedItem = selectedItem.Parent;
}
Alternatively, you could use CTE (Common Table Expression).
var parents = db.Database.SqlQuery<int>("sql statement");
Once you have a list of parents, you can use Contains.
return Json(db.Contents
.Where(p => p.ParentId == parentId)
.Select(p => new
{
id = p.Id,
name = p.Name
isSelectedValueUnderThisHierarchy = p.ParentId.HasValue && parents.Contains(p.ParentId.Value)
});
UPDATE: CTE Example
You'd probably want to use a stored procedure, but this code should work.
var sql = #"with CTE as
(
select ParentId
from Contents
where Id = {0}
union all
select Contents.ParentId
from Contents
inner join CTE on Contents.Id = CTE.ParentId
)
select *
from CTE
where ParentId is not null";
var parents = db.Database.SqlQuery<int>(string.Format(sql, selectedItem)).ToList();

adding a record to a LINQ object (concat) taking values from another

Hi i'm looking for some help in how to append rows to an existing LINQ object. In the controller method below I have two result sets, i'm looping the Sites and want to add a record to the 'results' object for each record in the Sites object.
I've tried concat etc but not getting anywhere, just need s small example to assist, many thanks in advance, J
public IQueryable<UsersToSite> FindAllUsersToSites(int userId,SystemType obj)
{
var results = (from usersToSite in this._db.UsersToSites
where usersToSite.UserId == userId &&
usersToSite.SystemTypeId == obj
orderby usersToSite.Site.SiteDescription
select usersToSite);
// Now for each remaining Site append a record thats not physically in the database. From the view the user will be able to click these records to ADD new
// I'll then build in a search
var sites = (from site in this._db.Sites
where !(from o in _db.UsersToSites where (o.UserId == userId && o.SystemTypeId == obj) select o.SiteId).Contains(site.SiteId)
orderby site.SiteDescription
select site);
foreach (var site in sites)
{
// HERE I want to create the new ROW in results object
//results = new[results] { new { UsersToSiteId = null, AccessTypeId = null } }.Concat(sites);
//SiteId=site.SiteId,
//UsersToSiteId = 0,
//AccessTypeId = 0,
//UserId = userId
}
return results;
}
I don't think you can, if you want to have keep queryable.
However, if you materialize the results with ToList(), then you can:
var sites = (from site in this._db.Sites
where !(from o in _db.UsersToSites where (o.UserId == userId && o.SystemTypeId == obj) select o.SiteId).Contains(site.SiteId)
orderby site.SiteDescription
select site)
.ToList();
sites.Add(new Site { UsersToSiteId = null, etc });
If it was LINQ to Objects, you could do Concat.
The problem here that it can't do ConcatLINQ query that will have one part from SQL and another from objects. You need to materialize results first and then concat to object.

Resources