【问题标题】: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
    相关资源
    最近更新 更多