Where are Duties (table name) stored in AX? - x++

I want to access Security duties (in code), but I don't know where they are stored (in which table)?
Privileges are stored in SecurityTask, now I need to know where duties are stored in AX 2012.
Thank you.

Security duties are in table SecurityTask with Type equal to 1 (SecurityTaskType::Duty).
Security privileges are in table SecurityTask with Type equal to 0 (SecurityTaskType::Privilege)
Security process cycles are in table SecurityTask with Type equal to 2 (SecurityTaskType::ProcessCycle).
All these objects are also in table (or rather view) SysModelElement (Duties with ElementType == 135).

I found it here: http://arsalanax.blogspot.be/2012/02/role-based-security-in-ax.html
Roles are stored in SecurityRole
User to role mappings in SecurityUserRole
Duties & privileges stored in SecurityTask
Duty to privileges mappings are stored in SecuritySubTask
Role to duty mappings are stored in SecurityRoleTaskGrant
UPDATE (query added)
SecurityTaskEntryPoint taskEntryPoint;
SecurityRole role;
SecurityRoleTaskGrant taskGrant;
SecuritySubTask subTask;
SecurityTask privilege;
str privName;
str dutyName;
str entrName;
str accessLevel;
;
while select taskEntryPoint
join subTask
where subTask.SecuritySubTask == taskEntryPoint.SecurityTask
join taskGrant
where taskGrant.SecurityTask == subTask.SecurityTask
join role
where role.RecId == taskGrant.SecurityRole
&& role.AotName like 'Sales*'
//|| role.AotName like 'System*'
{
if (subTask.RecId)
{
switch (taskEntryPoint.PermissionGroup)
{
case AccessRight::View:
accessLevel = "R";
break;
case AccessRight::Edit:
accessLevel = "U";
break;
case AccessRight::Add:
accessLevel = "C";
break;
case AccessRight::Delete:
accessLevel = "D";
break;
default:
accessLevel = "";
break;
}
}
select privilege
where privilege.RecId == taskGrant.SecurityTask
&& SecurityTaskType::Duty == privilege.Type;
dutyName = privilege.AotName;
select privilege
where privilege.RecId == subTask.SecuritySubTask
&& SecurityTaskType::Privilege == privilege.Type;
privName = privilege.AotName;
info(strFmt("EP: %1, Pr: '%2', Du: %3, Ro: %4, Ac: %5", taskEntryPoint.EntryPoint, privName, dutyName, role.AotName, accessLevel));
}

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.

EF delete a reference in bridge table

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();

Linq Query Optimization joining of tables

So I have a linq query, where s1.code comes from an object before this linq query.
var q1 = from cf in db.Control_Franchises
join t1 in db.Territories
on SqlFunctions.StringConvert((double)cf.FranchiseID).Trim()
equals t1.FranchiseID.Trim()
join cu in db.Control_Users on t1.FK_CompanyID equals cu.PrimaryCompanyID
join u in db.Users on cu.UserID.ToLower() equals u.Username.ToLower()
where cf.Status == "ACTIVE"
&& cf.FranchiseID > 1000
&& cu.UserType == "Franchisee"
&& cu.Status == "ACTIVE"
&& t1.Province == s1.Code
orderby cu.LastName ascending, cf.FranchiseID ascending
select new
{
FranchiseId = cf.FranchiseID,
Province = cf.StateCode,
DisplayName = cu.LastName + ", " + cu.FirstName,
UserId = u.PK_UserID
};
I have the same block of code but this time in my where clause, I changed the filter from using t1.Province == s1.Code to cf.StateCode == s1.Code
var q1 = from cf in db.Control_Franchises
join t1 in db.Territories
on SqlFunctions.StringConvert((double)cf.FranchiseID).Trim()
equals t1.FranchiseID.Trim()
join cu in db.Control_Users on t1.FK_CompanyID equals cu.PrimaryCompanyID
join u in db.Users on cu.UserID.ToLower() equals u.Username.ToLower()
where cf.Status == "ACTIVE"
&& cf.FranchiseID > 1000
&& cu.UserType == "Franchisee"
&& cu.Status == "ACTIVE"
&& cf.StateCode == s1.Code // DIFFERENT FROM ABOVE
orderby cu.LastName ascending, cf.FranchiseID ascending
select new
{
FranchiseId = cf.FranchiseID,
Province = cf.StateCode,
DisplayName = cu.LastName + ", " + cu.FirstName,
UserId = u.PK_UserID
};
Now the first query runs 10 times as fast as the second one.
How I am measuring the speed though, is the load time of my Edit Page, which in turn is loading a mvc tree view of the nodes. This query as well portions of a different query.
Now I'm trying to understand why my first query loads much faster and the only reasoning I can think of is because I am doing a condition on a table that will be joined, so rather then joining the entire "Territories" table with "Control_Franchises" I am only joining a portion of the "Territories" table.
Any thoughts?
Most likely the two different columns t1.Province and cf.StateCode are indexed differently in underlying data source (or one isn't at all)

Need help to build an EF query with LEFT JOIN

I can't find the correct way to build an EF (4.1) query that will return the same result as this SQL containing a LEFT JOIN:
SELECT
s.id_service,
s.description,
x.id_service as isDisponible
FROM
role.service_disponible s
LEFT JOIN
role.service_disponible_x_ue x
ON s.id_service = x.id_service AND x.id_ue = 1 and flg_actif = '1'
In fact I'm just trying to obtain the complete list of services disponible (ServiceDisponible) adding a field that tell me if service is disponible for a specific entity (filtered with the id_ue) which information come from a many to many related table (ServiceDisponibleXUe).
My model is:
Ideally, I would like this query to return this viewModel object what is basically my serviceDisponible domain with one more field indicating the disponibility of the service.
public ServiceDisponibleViewModel(ServiceDisponible ServiceDisponible, bool isDisponible)
{
this.serviceDisponible = serviceDisponible;
this.isDisponible = isDisponible;
}
What I have so far is this query but the syntax is invalid:
services = context.ServiceDisponible
.Select(a => new ServiceDisponibleViewModel
{
c => new ServiceDisponible
{
id_service = a.id_service,
description = a.description
},
isDisponible = a.ServiceDisponibleXUe
.Any(b => b.flg_actif && b.id_ue == idUe)
}).ToList();
Try this:
ServiceDisponibleViewModel services =
from sd in context.ServiceDisponible
from sdx in context.ServiceDisponibleXUe
.Where(x => x.id_ue == 1 && flg_actif == '1' && x.id_service == sd.id_service)
.DefaultIfEmpty()
select new ServiceDisponibleViewModel(
new ServiceDisponible
{
id_service = sd.id_service,
description = sd.description
},
sdx.id_service
);
Having SQL as example often makes one jump to a join in linq. But using navigation properties produces much more succinct syntax:
from sd in context.ServiceDisponible
from sdx in sd.ServiceDisponibleXUes.Where(x => x.id_ue == 1
&& x.flg_actif == "1")
.DefaultIfEmpty()
select new
{ sd.id_service,
sd.description,
isDisponible = sdx.id_service
};
(I couldn't help using the plural form of ServiceDisponibleXUe which imo is more clear).

Not getting data of Include object -- Entity Framework

I am getting the problem with "Include" in Entity Framework. Lets assume that I have two tables with foreign key relation.
var result = (from u in entity.Table1.Include("Table2")
join o in entity.Table2 on u.Column1 equals o.Column1
where u.Column2 == “abc” && u.Column3 == ‘xyz’
&& o.Column5 == organizationCode
select u).FirstOrDefault();
With the above query its not returning the Table2 object data in the result even though I have proper data in the database.
The issue i have found with above query is, if query is having "Include" as well as "Join", EF not considering "Include" tables. This is my assumption.
After spending some time I got the data by writing a dummy query below that. Please see the both queries below.
var result = (from u in entity.Table1.Include("Table2")
join o in entity.Table2 on u.Column1 equals o.Column1
where u.Column2 == “abc” && u.Column3 == ‘xyz’
&& o.Column5 == organizationCode
select u).FirstOrDefault();
var resultOrg = (from o in entity. Table2
where o.Column5 == organizationCode
select o).FirstOrDefault();
After executing both queries I am getting the Include (Table2) data in the result variable. In this case unnecessarily I am executing one query which I want to avoid.
Please suggest me where we are doing wrong.
You cannot use Include if you are using join. There is now way around that. Moreover what you are trying to do is filtering include which is also not possible.
You can do this:
var result = (from u in entity.Table1.Include("Table2")
where u.Column2 == “abc” && u.Column3 == ‘xyz’ &&
u.Table2.Any(o => o.Column5 == organizationCode)
select u).FirstOrDefault();
But it will include all Table2 entities to filtered Table1 entities. You cannot restrict included values to only those having some organization code.
To filter navigation properties you must use projection:
var result = (from u in entity.Table1
where u.Column2 == “abc” && u.Column3 == ‘xyz’ &&
u.Table2.Any(o => o.Column5 == organizationCode)
select new
{
Table1 = u
Table2 = u.Table2.Where(o => o.Column5 == organizationCode)
}).FirstOrDefault();
You must project either to anonymous type or custom type.
The reason why your second query works is automatic wiring of relations for tracked properties and it is another way how to filter relations but in such case this is enough:
var result = (from u in entity.Table1
where u.Column2 == “abc” && u.Column3 == ‘xyz’ &&
u.Table2.Any(o => o.Column5 == organizationCode)
select u).FirstOrDefault();
var resultOrg = (from o in entity. Table2
where o.Column5 == organizationCode
select o).FirstOrDefault();

Resources