#c# #asp.net #database #linq #asp.net-core
#c# #asp.net #База данных #linq #asp.net-core
Вопрос:
У меня есть три таблицы.
- Организационная единица
- пользователь
- Задачи
Я хочу вернуть данные из таблицы задач, где авторизованный пользователь находится в определенном отделе, и пользователь тоже находится в этом отделе. Например, Салли работает в отделе кадров. Она хочет просмотреть задачи Джима. Джим также работает в отделе кадров с Салли, поэтому ей разрешено просматривать его задачи. Однако она не должна иметь возможности просматривать задачи Джона, поскольку он находится в отделе продаж.
organisationalUnit
--------------------
ID | name
--------------------
1 | HR
2 | Sales
Users
----------------------------------------
ID | name | OUID(FK)
----------------------------------------
4 | Jim | 1
5 | Sally | 1
6 | John | 2
Tasks
----------------------------------------------
ID | TaskInfo | userID(FK)
-----------------------------------------------
1 | Task for Jim | 4
2 | Task for john | 5
3 | Task for Sally | 6
текущий код LINQ
public async Task<IEnumerable<TaskSchedule>> GetTasks(string RoleName)
{
// return back ou ID
var OUObjReturned = _context.OrganisationalUnits.Where(o => o.Name == RoleName).ToList();
var OUID = OUObjReturned[0].Id;
// get users based on the OUID
var userObjects = _context.Users.Where(u => u.OUId == OUID).ToList();
// returns back with an array of users that have the Organisational unit ID
var userIDFromObject = userObjects[0].Id;
//need further code to query the task table to return back tasks based on userID
}
Теперь я застрял на том, что делать после того, как я верну список пользователей с их идентификаторами. Есть ли лучший способ закодировать запрос LINQ, чем тот, который я сделал выше?
Запрос LING должен иметь возможность возвращать список задач на основе идентификатора OrganizationalUnit, который сначала отправляется в запрос. В приведенном выше случае отправка идентификатора организационной единицы, равного 1, должна вернуть строки задачи 1 и 2, поскольку Джим и Салли находятся в OUID 1.
Ответ №1:
Попробуйте приведенный ниже linq:
var roleName = "HR";
var tasks = (from t in _context.Tasks
join u in _context.Users on t.UserId equals u.Id
join o in _context.OrganisationalUnits on u.OUID equals o.Id
where o.Name == RoleName
select t).ToList();
Ниже приведен Тест:
public class OrganisationalUnit
{
public int Id { get; set; }
public string Name { get; set; }
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("OrganisationalUnit")]
public int OUID { get; set; }
}
public class Task
{
public int Id { get; set; }
public string TaskInfo { get; set; }
[ForeignKey("User")]
public int UserId { get; set; }
}
Результат:
Ответ №2:
public async Task<IEnumerable<TaskSchedule>> GetTasks(string RoleName)
{
// Here you found the OU
var OUObjReturned = await _context.OrganisationalUnits
.Where(o => o.Name == RoleName)
.FirstOrDefault();
// Now get list of users id
var userObjects = await _context.Users
.Where(u => u.OUId == OUObjReturned.ID)
.Select(u => u.ID)
.ToListAsync();
// Return Tasks
return await _context.Tasks
.Where(t => userObjects.Contains(t.UserID)
.ToListAsync();
}
Но есть другой способ: (при условии, что FK хорошо сконфигурирован) и модели включают свойства навигации, например: Пользователь должен включить ссылку на OrganizationalUnit:
public class User
{
public int ID {get; set;}
public string Name {get; set;}
public OrganizationalUnit OU {get; set;}
public int OUID {get; set;}
}
Теперь вы можете запрашивать напрямую, используя свойства навигации, см. Отношения EF Net Core
public async Task<IEnumerable<TaskSchedule>> GetTasks(string RoleName)
{
// Return Tasks
return await _context.Tasks
.Include(t => t.User)
.Where(t => User.OU.Name == RoleName)
.ToListAsync();
}