Сначала код EF6 — запрос иерархии хранимых процедур с несколькими таблицами

#c# #sql #entity-framework #lambda #entity-framework-6

#c# #sql #entity-framework #лямбда #entity-framework-6

Вопрос:

Я совсем новичок в EF6, и я хотел бы закодировать эту хранимую процедуру с помощью EF. Я начал играть со свойствами навигации и «.Включает в себя»но это слишком сложно для меня.

Некоторые пояснения по этому поводу: у меня есть пользователи с назначенным идентификатором роли. Идентификатор набора ролей связан с ModuleGroup. ModuleGroup содержит модули, поэтому пользователь может иметь доступ к этим модулям на основе его RoleSetId. Он также может получить доступ к модулям из дочерних групп модулей. Таким образом, ModuleGroup может содержать модули, но он также может содержать ModuleGroups.

Вот хранимая процедура, которая получает идентификатор из ModuleGroup на основе RoleSetId, а затем выполняет рекурсивный запрос, чтобы получить все ModuleGroups, доступные для RoleSetId, затем возвращает модули, содержащиеся в выбранных ModuleGroups:

 ALTER PROCEDURE [dbo].[GetModules] @RoleSetId int
AS

    DECLARE @id INT
    SET @id = (SELECT TOP 1 Id FROM ModuleGroup WHERE RoleSetId = @RoleSetId);

    WITH groups AS (
        SELECT mgg.ModuleGroupId, mgg.ModuleGroupSubGroupId
        FROM [dbo].[ModuleGroupSubGroup] mgg
        WHERE ModuleGroupId = @id
        UNION ALL
        SELECT mgg2.ModuleGroupId, mgg2.ModuleGroupSubGroupId
        FROM [dbo].[ModuleGroupSubGroup] mgg2
        JOIN groups g ON g.ModuleGroupSubGroupId = mgg2.ModuleGroupId
    )
    SELECT m.*
    FROM Module m
    INNER JOIN ModuleGroupModule mgm ON mgm.ModuleId = m.InternalId
    WHERE mgm.ModuleGroupId IN (SELECT g.ModuleGroupSubGroupId FROM groups g) OR mgm.ModuleGroupId = @id
    OPTION (MAXRECURSION 1000)
 

Вот мои таблицы (упрощенные) :

 [Table("ModuleGroup")]
public class ModuleGroup : BaseModel
{
    [Key]
    public int Id { get; set; }

    public ICollection<ModuleGroupModule> ModuleGroupModules { get; set; }

    public int RoleSetId { get; set; }
}

[Table("ModuleGroupSubGroup")]
public class ModuleGroupSubGroup : BaseModel
{
    [Key]
    [Column(Order = 0)]
    public int ModuleGroupId { get; set; }

    [Key]
    [Column(Order = 1)]
    [ForeignKey(nameof(ModuleGroup))]
    public int ModuleGroupSubGroupId { get; set; }

    public ModuleGroup ModuleGroup { get; set; }
}


[Table("ModuleGroupModule")]
public class ModuleGroupModule : BaseModel
{
    [Key]
    [Column(Order = 0)]
    [ForeignKey(nameof(ModuleGroup))]
    public int ModuleGroupId { get; set; }

    [Key]
    [Column(Order = 1)]
    [ForeignKey(nameof(Module))]
    public int ModuleId { get; set; }

    public Module Module { get; set; }

    public ModuleGroup ModuleGroup { get; set; }
}

[Table("Module")]
public class Module : BaseModel
{
    [Key]
    public int Id { get; set; }

    public ICollection<ModuleGroupModule> ModuleGroupModules { get; set; }
}
 

Чтобы быть более понятным, вот схема БД :

введите описание изображения здесь

Спасибо.

Комментарии:

1. LINQ не имеет соответствующей конструкции запроса к рекурсивному общему табличному выражению. Вы можете продолжать использовать хранимую процедуру или обрабатывать строки в процедурном коде на клиенте, либо сначала извлекая все строки, либо используя отложенную загрузку.

2. Спасибо, я боялся такого ответа. Поскольку мы отключили отложенную загрузку в нашем проекте, я думаю, мне придется сначала получить строки. Но я должен применить другие фильтры, мой способ сделать это так: query = ctx.Database . SqlQuery<T>(«SPD»). ToList(), а затем result = запрос. AsQueryable() . Включает …. Еще один способ избежать . ToList(), за которым следует . AsQueryable() ?