2

I need some help on a sql query, for which I am using EntityFramework as ORM.

I have a User-- Group Many to Many relationship, i.e one user can belong to more than one group and one group can have more than 1 user.

The way I have done the mapping is..

USER tbl, Usr_Grp table, and Group Table where PK = Primary Key, FK = Foreign Key

USER table has --> UserId(PK) , UserName
Group table has --> GroupId (PK), GroupName
Usr_Grp table has --> Id(PK), UUserId(FK to usertable), GGroupId (FK to GroupTable)

The issue that I am facing is... In my api , I will get a set of GroupId's and I want to find only those Users that belong to all these GroupId's ( i.e all the groups that are passes in).

Is there a way to write this query in entity framework or Sql. I would really appreciate any help I can get on this.

-RN

Ben
  • 723
  • 4
  • 10
  • 18
  • I'm not very familiar with Entity Framework, but would the sql query help that I would execute? – Stefan H Dec 18 '10 at 06:34
  • Yep that would definetly help. – Ben Dec 18 '10 at 06:35
  • Please have a look : http://stackoverflow.com/questions/553918/entity-framework-and-many-to-many-queries-unusable – KV Prajapati Dec 18 '10 at 06:36
  • @adatapost That question is little different, I have a set of roles that the user has to belong to. I am not having issues with EF, I can figure that out but I am not able to get the Correct SQL query. – Ben Dec 18 '10 at 06:41

3 Answers3

6

Junction table Usr_Grp shouldn't have Id. If you create complex primary key over (UUserId, GGroupId), then EF automatically would understand, that it is Many-To-Many relation.

If you make your relations as follows:alt text

Then EF will generate entities with Many-To-Many relations:alt text

After you have everything set up you can easily use such code:

var ids = new List<int>{1, 2, 3, 4}; // GroupIds you need
context.Groups
        .Where(x=> ids.Contains(x.Id))
        .SelectMany(x=>x.Users)
        .Distinct()
        .ToArray();

If you cannot change model, then just use such linq query:

context.Grp_Usrs
        .Where(x=> ids.Contains(x.GroupId))
        .SelectMany(x=>x.Users)
        .Distinct()
        .ToArray();
The Smallest
  • 5,713
  • 25
  • 38
  • Isn't it possible to simply remove the Usr_Grp entity, and then use it to form a many-many relationship between the two tables, *without* removing the `Id` column? I know EF won't do it if you just drag the table onto the designer, but can't you manually do it? – Kirk Broadhurst Dec 18 '10 at 09:24
  • @Kirk Broadhurst - Never tried to do such a thing. I don't like editing edmx file manually. I suppose it's not possible, but it is nothing, but my feelings. I really could be wrong. You can ask this as separate question on stackoverflow, cleaver people could answer. – The Smallest Dec 18 '10 at 10:46
  • @ Ben - see last lines of answer if you cannot change model. It's not as clear as Many-To-Many relation, but it should work. – The Smallest Dec 18 '10 at 23:36
  • I'm not suggesting editing the edmx, but just right click on the designer and add a new relationship between the two tables. – Kirk Broadhurst Dec 19 '10 at 10:32
0

Try this method:

var gid = new List<int> {1, 2, 3, 4};
var users_id = entity.Usr_Grp.where(x=> gid.Contains(x.uid);

Hope it helps!

Tee Wu
  • 569
  • 2
  • 9
0
    //Here is a LinqToSql example but it should work with EF too.Taking into consideration your mappings I would have the following approach in handling a many to many relationship:

    //1. First You need to save you records into the tables as many to many relationship
    [Test]
    public void CanSaveGroupUsers()
    {
        var group = Group { CreatedDate = DateTime.UtcNow, Name = "The Rookies" };
        var groupId = _groupRepository.SaveGroup(group);

        var user = new User { CreatedDate = DateTime.Now, Name = "Justin Bieber" };
        var userId = _userRepository.SaveUser(user);

        var userGroup = new UserGroup { GroupId = groupId, UserId = userId };
        _group.SaveUserGroup(userGroup);
    }

    //2. Then you can retrive them this way:
    [Test]
    public void CanGetGroupUsers()
    {
        var groupIds = new List<int>{1,2,3,4};
        var users = _usersRepository.GetAllUsers();
        var specificUsersList = (users.AsQueryable().Where(user => groupIds.Contains(user.UserGroups.FirstOrDefault().GroupId)));
    }

    //3. I attached my repository code just in case
    public IQueryable<User> GetAllUsers()
    {
        _db.ObjectTrackingEnabled = false;
        return _db.Users;
    }
    public int SaveGroup(Group Group)
    {
        var dbGroup = new Group
        {
            Name = Group.Name,
            CreatedDate = Group.CreatedDate
        };
        _db.Groups.InsertOnSubmit(dbGroup);
        _db.SubmitChanges();
        return dbGroup.Id;
    }

    public int SavUser(User user)
    {
        var dbUser = new User
        {
            CreatedDate = user.CreatedDate,
            Name = user.Name
        };
        _db.Users.InsertOnSubmit(dbUser);
        _db.SubmitChanges();
        return dbUser.UserId;
    }

     public void SaveUserGroup(UserGroup userGroup)
    {
        var dbUserGroup = new UserGroup
        {
            GroupId = userGroup.GroupId,
            UserId = userGroup.UserId

        };
        _db.UserGroups.InsertOnSubmit(dbUserGroup);
        _db.SubmitChanges();
    }

    //Hope this helps:)
Vasile Laur
  • 699
  • 7
  • 16
  • EntityFramework will abstract the UserGroup table away into a pure relationship - so that `User` has a `Groups` property, and `Group` has a `Users` property. The UserGroup table won't appear in the generated namespace as an entity at all. – Kirk Broadhurst Dec 18 '10 at 09:22
  • Thanks for pointing this out. I usually use NHibernate where you also don't need the third table(GroupUsers) as you can specify the the manytomany mappings and you only need the users and group entities. Looks like is time for me to move from LinqToSql to EF :) – Vasile Laur Dec 18 '10 at 17:17