简化过于复杂的 LINQ 查询 - 查询

发布于 2024-09-26 11:12:40 字数 4840 浏览 2 评论 0原文

public partial class MembershipModule : BaseEntity<MembershipModule>
{
    /// <summary>
    /// Returns wheter a module is accessible
    /// </summary>
    public static bool IsAccessible(MembershipModule module)
    {
        // In absence of a module, no security applies to the page
        if(module == null)
            return true;

        return module.IsAccessible();
    }

    /// <summary>
    /// Returns whether the module is accessible
    /// </summary>
    /// <returns></returns>
    public bool IsAccessible()
    {
        // Skip unnecessary querying
        if(!MembershipUser.Connected)
            return this.Enabled && this.OfflineAccess;

        Guid accessGuid = MembershipAction.AccessGuid;

        // ModuleActions for this MembershipModule and the Access Action
        IQueryable<MembershipModuleAction> accessMA =
            from ma in LinqUtil.Context.MembershipModuleActions
            where ma.ModuleId.Equals(this.Id) && ma.ActionId.Equals(accessGuid)
            select ma;

        // RolePrivileges that grant access on this MembershipModule for the Current MembershipUser
        IQueryable<bool> accessRP =
            from rp in LinqUtil.Context.MembershipRolePrivileges
            where accessMA.Contains(rp.MembershipModuleAction)
            select rp.MembershipRole.MembershipUsers.Contains(MembershipUser.Current);

        return this.Enabled && (this.OfflineAccess || accessRP.ToList().FirstOrDefault());
    }

    /// <summary>
    /// Returns all accessible modules that can be accessed by the logged user
    /// </summary>
    /// <returns></returns>
    public static IEnumerable<MembershipModule> GetAccesible()
    {
        // Skip unnecessary querying
        if(!MembershipUser.Connected)
            return LinqUtil.Context.MembershipModules.Where(m => m.Enabled && m.OfflineAccess).ToList();

        Guid accessGuid = MembershipAction.AccessGuid;

        // ModuleActions for any MembershipModule with the Access Action
        IQueryable<MembershipModuleAction> accessMA =
            from ma in LinqUtil.Context.MembershipModuleActions
            where LinqUtil.Context.MembershipModules.Any(m => m.Enabled && m.Id.Equals(ma.ModuleId)) && ma.ActionId.Equals(accessGuid)
            select ma;

        // RolePrivileges that grant access on those MembershipModule for the Current MembershipUser
        IQueryable<MembershipRolePrivilege> accessRP =
            from rp in LinqUtil.Context.MembershipRolePrivileges
            where accessMA.Any(ma => rp.MembershipModuleAction.Id.Equals(ma.Id)) && rp.MembershipRole.MembershipUsers.Any(u => u.Id.Equals(MembershipUser.Current.Id))
            select rp;

        // Accessible modules
        var modules =
            from m in LinqUtil.Context.MembershipModules
            where accessMA.Any(ma => ma.MembershipModule.Id.Equals(m.Id)) && accessRP.Any(rp => rp.MembershipModuleAction.ModuleId.Equals(m.Id))
            select m;

        return modules.ToList();
    }

    /// <summary>
    /// Menu Items that can be displayed on the current web page
    /// </summary>
    public static IEnumerable<MembershipModule> GetMenuItems(string uriPrefix)
    {
        IEnumerable<MembershipModule> list = GetAccesible();

        return list.Where(m => m.UriPrefix.Equals(uriPrefix) && m.MenuItem).OrderBy(m => m.Position);
    }
}

这目前有效,但出于某种原因,我忍不住认为代码看起来很丑(特别是两个非常相似的静态和实例函数,它们让我获得可访问的页面

关于如何重构它以使其看起来更有吸引力有什么想法吗?

额外问题:

Guid accessGuid = MembershipAction.AccessGuid;

如果不使用该行,而只是在查询中调用MembershipAction.AccessGuid,我会收到一条错误消息,告诉我一些晦涩的内容:

班级成员 MembershipAction.AccessGuid 是 未映射。

棘手的部分就在这里:在静态 GetAccessible() 函数中,这不会发生。我可以将 MembershipAction.AccessGuid 添加到查询中,但在实例 IsAccessible() 函数中我遇到了此问题。

作为记录,这里是 MembershipAction:

public partial class MembershipAction : BaseEntity<MembershipAction>
{
    public const string AccessPrivilege = "Access";

    private static Guid accessGuid = Guid.Empty;
    public static Guid AccessGuid
    {
        get
        {
            if(accessGuid == Guid.Empty)
            {
                IQueryable<Guid> query = from a in LinqUtil.Context.MembershipActions
                                         where a.Name.Equals(AccessPrivilege)
                                         select a.Id;

                accessGuid = query.ToList().FirstOrDefault();
            }

            return accessGuid;
        }
    }
}
public partial class MembershipModule : BaseEntity<MembershipModule>
{
    /// <summary>
    /// Returns wheter a module is accessible
    /// </summary>
    public static bool IsAccessible(MembershipModule module)
    {
        // In absence of a module, no security applies to the page
        if(module == null)
            return true;

        return module.IsAccessible();
    }

    /// <summary>
    /// Returns whether the module is accessible
    /// </summary>
    /// <returns></returns>
    public bool IsAccessible()
    {
        // Skip unnecessary querying
        if(!MembershipUser.Connected)
            return this.Enabled && this.OfflineAccess;

        Guid accessGuid = MembershipAction.AccessGuid;

        // ModuleActions for this MembershipModule and the Access Action
        IQueryable<MembershipModuleAction> accessMA =
            from ma in LinqUtil.Context.MembershipModuleActions
            where ma.ModuleId.Equals(this.Id) && ma.ActionId.Equals(accessGuid)
            select ma;

        // RolePrivileges that grant access on this MembershipModule for the Current MembershipUser
        IQueryable<bool> accessRP =
            from rp in LinqUtil.Context.MembershipRolePrivileges
            where accessMA.Contains(rp.MembershipModuleAction)
            select rp.MembershipRole.MembershipUsers.Contains(MembershipUser.Current);

        return this.Enabled && (this.OfflineAccess || accessRP.ToList().FirstOrDefault());
    }

    /// <summary>
    /// Returns all accessible modules that can be accessed by the logged user
    /// </summary>
    /// <returns></returns>
    public static IEnumerable<MembershipModule> GetAccesible()
    {
        // Skip unnecessary querying
        if(!MembershipUser.Connected)
            return LinqUtil.Context.MembershipModules.Where(m => m.Enabled && m.OfflineAccess).ToList();

        Guid accessGuid = MembershipAction.AccessGuid;

        // ModuleActions for any MembershipModule with the Access Action
        IQueryable<MembershipModuleAction> accessMA =
            from ma in LinqUtil.Context.MembershipModuleActions
            where LinqUtil.Context.MembershipModules.Any(m => m.Enabled && m.Id.Equals(ma.ModuleId)) && ma.ActionId.Equals(accessGuid)
            select ma;

        // RolePrivileges that grant access on those MembershipModule for the Current MembershipUser
        IQueryable<MembershipRolePrivilege> accessRP =
            from rp in LinqUtil.Context.MembershipRolePrivileges
            where accessMA.Any(ma => rp.MembershipModuleAction.Id.Equals(ma.Id)) && rp.MembershipRole.MembershipUsers.Any(u => u.Id.Equals(MembershipUser.Current.Id))
            select rp;

        // Accessible modules
        var modules =
            from m in LinqUtil.Context.MembershipModules
            where accessMA.Any(ma => ma.MembershipModule.Id.Equals(m.Id)) && accessRP.Any(rp => rp.MembershipModuleAction.ModuleId.Equals(m.Id))
            select m;

        return modules.ToList();
    }

    /// <summary>
    /// Menu Items that can be displayed on the current web page
    /// </summary>
    public static IEnumerable<MembershipModule> GetMenuItems(string uriPrefix)
    {
        IEnumerable<MembershipModule> list = GetAccesible();

        return list.Where(m => m.UriPrefix.Equals(uriPrefix) && m.MenuItem).OrderBy(m => m.Position);
    }
}

This currently works, but for some reason I can't help but to think the code looks ugly (particularly the two very similar static and instance functions that get me the accessible pages

Any thoughts on how to refactor this to look more appealing?

Bonus question:

Guid accessGuid = MembershipAction.AccessGuid;

Without using that line, and just calling MembershipAction.AccessGuid in my query, I get an error telling me something obscure:

Class member
MembershipAction.AccessGuid is
unmapped.

The tricky parts comes here: in the static GetAccessible() function this doesn't happen. I can just add MembershipAction.AccessGuid to the query, but it's in the instance IsAccessible() function that I get this problem.

For the record, here's MembershipAction:

public partial class MembershipAction : BaseEntity<MembershipAction>
{
    public const string AccessPrivilege = "Access";

    private static Guid accessGuid = Guid.Empty;
    public static Guid AccessGuid
    {
        get
        {
            if(accessGuid == Guid.Empty)
            {
                IQueryable<Guid> query = from a in LinqUtil.Context.MembershipActions
                                         where a.Name.Equals(AccessPrivilege)
                                         select a.Id;

                accessGuid = query.ToList().FirstOrDefault();
            }

            return accessGuid;
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

別甾虛僞 2024-10-03 11:12:40

需要指出的是,这是个人观点,我们在这里都有这样的观点:

  1. 在查询中放弃使用 lambda 表达式。选择一种风格并使用它,伙计。
  2. 去掉 where 子句中的 & 符号。您可以使用以 where 开头的另一行得到相同的结果。
  3. 不要害怕查询另一个查询。如果它更容易理解,就没有理由不这样做。编译器会将它们组合成一个查询。
  4. 许多人会指出静态方法通常会带来代码异味。为什么需要静态方法和实例方法?也许课堂上的一些澄清是有必要的。

Mentioning that this is personal opinion and we all have them here goes:

  1. Ditch the use of lambda expressions inside the queries. Pick a style and use it dude.
  2. Get rid of the ampersand in the where clause. You can get the same thing with another line starting with where.
  3. Don't be afraid to query another query. If it makes it easier to understand, there is no reason to not do it. The compiler will combine them into a single query for you.
  4. Many will point out that static methods often point to code smell. Why do you need both static and instance methods? Perhaps some clarity in the class is in order.
乖乖哒 2024-10-03 11:12:40

是不是很简单:

public static IEnumerable<MembershipModule> GetAccesible()
{
    // Skip unnecessary querying
    if(!MembershipUser.Connected)
        return LinqUtil.Context.MembershipModules.Where(m => m.Enabled && m.OfflineAccess).ToList();

    // Accessible modules
    var modules =
        from m in LinqUtil.Context.MembershipModules
        where m.IsAccessible()
        select m;

    return modules.ToList();
}

Isn't it simply:

public static IEnumerable<MembershipModule> GetAccesible()
{
    // Skip unnecessary querying
    if(!MembershipUser.Connected)
        return LinqUtil.Context.MembershipModules.Where(m => m.Enabled && m.OfflineAccess).ToList();

    // Accessible modules
    var modules =
        from m in LinqUtil.Context.MembershipModules
        where m.IsAccessible()
        select m;

    return modules.ToList();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文