【问题标题】:is this an elegant way to implement this association scenario in a custom orm?这是在自定义 orm 中实现此关联场景的一种优雅方式吗?
【发布时间】:2016-12-30 22:48:01
【问题描述】:

我正在使用 Dapper 构建自定义 ORM。我有以下表格:

  • 用户
  • 角色
  • 权限
  • 角色权限

我的存储过程有 2 个选择:1 个用于基本用户信息,1 个用于用户角色信息。基本用户信息被反序列化为用户对象。 RolePermission 信息被反序列化为自定义 RolePermission 对象,然后以编程方式关联到 User 对象。在自定义 ORM 中实现对象图的复杂程度如何?例如,EF 采用了一种简单易用的 OO 方法来获取这样的角色名称:User.UserRoles.Role.Name。但是,这是通过使用复杂而复杂的 f/w 来实现的,该 f/w 根据 db fk 关联自动映射实体连接。它还带来了性能开销。我的想法是按如下方式创建我的实体类:

  • MyCompany.Entities.Entity.User.User
  • MyCompany.Entities.Entity.User.RolePermission

因此,我的 RolePermission 对象将完全针对用户实体量身定制,没有外部依赖项。这将使 RolePermission 对象在 User 对象的上下文中尽可能轻量级。它不需要任何额外的属性来支持其他实体/域/用法。这似乎是一个优雅(简单、有效、高效)的解决方案。您对这种在自定义 ORM 中创建复杂对象的方法有何看法?

【问题讨论】:

    标签: oop orm dapper data-access-layer


    【解决方案1】:

    我一直在做这种事情,这真的很容易。您将在两个查询中执行此操作。这两个查询可以在同一个存储过程中并返回不同的结果集,也可以是对数据库的两个单独调用。即使我们使用允许返回多个结果集的 mssql,我通常也会使用后者。

    首先:您正在查询用户(浅层)和可选的用户详细信息,包括角色信息(深层)。

    public IEnumerable<User> GetUsers(int? userID, bool withDetails)
            {
                var users = db.Query<User>(@"   select * 
                                                from dbo.Users u 
                                                where (@userID IS NULL OR u.Id = @userID)", new { userID });
    
                if (withDetails)
                {
                    var rolePermissions = db.Query<RolePermission>(@"   select * 
                                                                        from dbo.RolePermissions rp 
                                                                        where rp.UserId IN (select val from dbo.udf_ConvertIntListToTable(@userId_list))", new { userId_list = String.Join(',', users.Select(s => s.UserId)) });
                    foreach(var user in users)
                    {
                        user.RolePermissions = rolePermissions.Where(w => w.UserId == user.UserId);
                    }
                }
            }
    

    几点说明:

    • dbo.udf_ConvertIntListToTable 非常成熟并且表现出色。搜索网络,你会找到它。如果你找不到它,我会把它作为要点加载。
    • RolePermission 需要引用外部用户(我使用了 UserId)。此外,该查询可能会映射您提到的其他数据(例如角色、权限等)
    • 我有大量的扩展来整理上述内容。我尽可能保持原始状态,以便您了解发生了什么。
    • 您现在有一个针对列表等的非常轻量级的查询 (withDetails=false),以及一个将所有数据很好地包装到其聚合根 (User) 中的繁重查询。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多