Search code examples
c#linqentity-frameworklinq-to-entitiesentitycollection

Returning a collection of objects where an objects property matches any property from another collection of objects using LINQ-to-Entities


I've been searching all day and can't find a solution to this...

I have an EntityCollection of Communication objects which each have an instance of an Intention object(one-to-one).

I also have a User object which has many instances of UserLocation EntityObjects(one-to-many)

  • Intention objects have a property UID.
  • UserLocation objects have a property LID.

  • I want to write a LINQ expression which returns all Communication objects where the UID property of the Intention instance associated to a Communication object equals ANY LID property of ANY instance of a UserLocation instance for a User object.

I've tried this

return _context.Communications.Where
(u => u.Intention.UID.Equals
(user.UserLocations.Select
(p => p.LID)));

and this

return _context.Communications.Where
(u => user.UserLocations.Any
(x => x.LID.Equals
(u.Intention.UID)));

and this

var thislist = from Intentions in _context.Intentions
                           join UserLocations in user.UserLocations
                           on Intentions.UID equals UserLocations.LID
                           select Intentions.UID;
            return _context.Communications.Where(u => u.Intention.Equals(thislist.Any()));

and this

var lidlist = user.UserLocations.Select(x => x.LID);
return _context.Communications.Where(x=> lidlist.Contains(x.Intention.UID)).ToList();

(this gives me an error on the Contains statement saying "Delegate System.Func<Communication,int,bool> does not take 1 argument", don't know how to fix)

Along with all these variations I have also:

  • modified my method to return IQueryable<Communication> and have also tried List<Communication> while appending ToList() to my queries.

Nothing works. Regardless of what I try I always end up with this exception

NotSupportedException was unhandled by user code

Unable to create a constant value of type 'PreparisCore.BusinessEntities.UserLocation'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.

What am i doing wrong??


Solution

  • Given this code:

    namespace CollectionsWithIntentions
    {
        using System.Collections.Generic;
        using System.Diagnostics;
        using System.Linq;
    
        internal class Program
        {
            #region Methods
    
            private static void Main(string[] args)
            {
                var communications = new[]
                    {
                        new Communication { Intention = new Intention { UID = 1 } },
                        new Communication { Intention = new Intention { UID = 2 } },
                        new Communication { Intention = new Intention { UID = 3 } },
                        new Communication { Intention = new Intention { UID = 4 } },
                    };
                var users = new[]
                    {
                        new User { UserLocations = new List<UserLocation>(new[] { new UserLocation { LID = 2 },new UserLocation{LID=5}  }) },
                        new User { UserLocations = new List<UserLocation>(new[] { new UserLocation { LID = 3 } }) }
                    };
    
                IEnumerable<Communication> res =
                    communications.Where(w => users.Any(a => a.UserLocations.Any(b=>b.LID == w.Intention.UID)));
                foreach (Communication communication in res)
                {
                    Trace.WriteLine(communication);
                }
            }
    
            #endregion
        }
    
        internal class Communication
        {
            #region Public Properties
    
            public Intention Intention { get; set; }
    
            #endregion
    
            #region Public Methods and Operators
    
            public override string ToString()
            {
                return string.Concat("Communication-> Intention:", this.Intention.UID);
            }
    
            #endregion
        }
    
        internal class Intention
        {
            #region Public Properties
    
            public int UID { get; set; }
    
            #endregion
        }
    
        internal class User
        {
            #region Public Properties
    
            public List<UserLocation> UserLocations { get; set; }
    
            #endregion
        }
    
        internal class UserLocation
        {
            #region Public Properties
    
            public int LID { get; set; }
    
            #endregion
        }
    }
    

    I get this result:

    Communication-> Intention:2
    Communication-> Intention:3
    

    Am I missing anything?