【问题标题】:Subsonic 3 simple repository many to many relationsSubsonic 3 简单存储库多对多关系
【发布时间】:2009-12-15 12:45:21
【问题描述】:

我在之前的帖子here on stackoverflow 中看到了一个关于多对多关系的示例。为简单起见,让我们看看这些类:

public class Role(){
    public int Id { get; set; }
    public string Rolename { get; set; }
    public string Description { get; set; }
}

public class User(){
    public int Id { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public IList<UsersAndRoles> UsersAndRoles { get; set; }
}

public class UsersAndRoles(){
    public int Id { get; set; }
    public User User { get; set; }
    public Role Role { get; set; }
}

这是写意的,所以请耐心等待。

现在对这些类进行 linq 查询的最佳方法是什么。可以说我想获得所有角色以及附加到他们的用户。有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: linq subsonic3 many-to-many


    【解决方案1】:

    我从来没有真正为这种事情编写过 linq 查询,因为我宁愿使用内置的活动目录存储库。如果你想走这条路:

    我首先要确保您的数据库配置了适当的外键:

    Table 'Roles'
    int Id (PK)
    
    Table 'Users'
    int Id (PK)
    
    Table 'UsersAndRoles'
    int RoleId (FK)
    int UserId (FK)
    

    如果正确完成,Subsonic3 将为您生成创建 IQueryable 子对象的类。如果要获取附加用户的所有角色,还需要将 UsersAndRoles 列表添加到角色对象。 您必须将其命名为不同的名称,因为您不能将其命名为与 IQueryable 对象相同的名称

    public partial class Role()
    {
        public int Id { get; set; }
        public string Rolename { get; set; }
        public string Description { get; set; }
    
        private IList<UsersAndRoles> _UserToRoleLinks
        public IList<UsersAndRoles> UserToRoleLinks 
        { 
            get
            {
                if(_UserToRoleLinks == null)
                    _UserToRoleLinks = this.UsersAndRoles.ToList();
                return _UserToRoleLinks;
            }
        }
    }
    
    public partial class UsersAndRoles
    {
        private Role _Role;
        public Role Role
        {
            get
            {
                if (_Role == null)
                    _Role = this.Roles.SingleOrDefault();
                return _Role;
            }
            set
            {
                _Role = value;
            }
        }
    
        private User _User;
        public User User
        {
            get
            {
                if (_User == null)
                    _User = this.Users.SingleOrDefault();
                return _User;
            }
            set
            {
                _User = value;
            }
        }
    }
    

    现在要获取附加用户的所有角色,请执行以下操作:

    var roles = Role.All();
    

    访问所有角色的所有用户:

    foreach (var role in roles)
    {
        foreach (var userToRoleLink in role.UserToRoleLinks)
        {
            var currentUser = userToRoleLink.User;
        }
    }
    

    当然这是徒手画的,所以肯定会出现编译错误。让我知道这是否有帮助。祝你好运!

    【讨论】:

    • 刚刚注意到您询问的是简单存储库...我认为其中的大部分内容都会对您有所帮助,但我从未使用过 SR,因此请尽量使用。
    【解决方案2】:

    Weel,因为我想在没有任何数据库查找的情况下保持我的实体清洁,所以我不能像你建议的那样做。

    我的实体是这样的:

    角色实体

    public class Role(){
        public int RoleId { get; set; }
        public string Rolename { get; set; }
        public string Description { get; set; }
        public IList<User> Users { get; set; }
        public Role()
        {
            RoleId = 0;
            Rolename = "";
            Description = "";
            Users = new List<User>();
        }
    }
    

    用户实体

    public class User(){
        public int UserId { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        public User()
        {
            UserId = 0;
            Username = "";
            Password = "";
            Email = "";
        }
    }
    

    用户和角色实体

    public class UsersAndRoles(){
        public int Id { get; set; }
        public int UserId { get; set; }
        public int RoleId { get; set; }
        public UsersInRoles()
        {
            Id = 0;
            UserId = 0;
            RoleId = 0;
        }
    }
    

    现在从我的存储库中,我尝试执行以下操作:

    public IList<Role> GetRolesAndUsers()
    {
        //--- Load all roles
        var roles = base.All<Role>();
    
        //--- Run through all roles and add the users to the roles.
        foreach (var role in roles)
        {
            //--- Load the users in the given role
            var users = (from u in base.All<User>()
                         join ur in base.All<UsersInRoles>() on role.RoleId equals ur.RoleId
                         where u.UserId == ur.UserId
                         select u).ToList();
    
            //--- Run through the list of users and add the user to the role
            foreach (var user in users)
            {
                role.Users.Add(user);
            }
        }
        //--- Return roles and users
        return roles.ToList();
    }
    

    但是,即使当我使用调试单步执行代码时,我可以看到用户被加载,用户也不会被添加到角色中。

    我在这里错过了什么?

    【讨论】:

    • 发现我必须将角色加载为 .ToList() 作为 base.All() 返回为 IQueryable ;o) 所以我将 base.All() 更改为base.All().ToList() 一切都像魅力;o)
    • 我不确定您所说的需要数据库查找的方法是什么意思(这两种情况下您都是从 IQueryable 对象创建列表),但如果您所做的工作对您有意义,那么去吧。我仍然认为我的方法会更容易;)
    • 在您在上面创建的实体中执行此操作“_User = this.Users.SingleOrDefault();”你不从数据库中加载一个用户吗?
    • 我正在做的是创建一个实体来表示用户和角色之间的链接。所以每个链接只有一个用户和一个角色。这就是为什么里面有 SingleOrDefault() 的原因。这样做的好处在于,如果链接具有任何属性(关系类型),则很容易将其添加进去。简而言之,一个角色将具有一个或多个 UsersAndRoles 实体,而一个用户将具有一个或多个 UsersAndRoles 实体。如果您不打算拥有任何具有多对多关系(链接属性)的有效负载,则可以消除链接实体。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多