这是在自定义orm中实现此关联方案的优雅方式吗?

时间:2016-08-24 00:05:32

标签: oop orm dapper data-access-layer

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

  • 用户
  • 作用
  • 权限
  • RolePermission

我的sproc有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对象将完全针对User实体进行定制,没有外部依赖关系。这将使RolePermission对象在User对象的上下文中保持尽可能轻量级。它不需要任何其他属性来支持其他实体/域/用法。这似乎是一种优雅(简单,有效,高效)的解决方案。您对在自定义ORM中创建复杂对象的此类方法有何看法?

1 个答案:

答案 0 :(得分:0)

我一直这样做,这真的很容易。你将在两个查询中完成。这两个查询可以在同一个sproc中并返回不同的结果集,也可以是对数据库的两个单独调用。我通常使用后者,即使我们使用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),以及一个较重的查询,所有数据都很好地包装到其聚合根(用户)中。