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

*爱你&永不变心* 提交于 2019-12-07 19:21:06

问题


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??


回答1:


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?




回答2:


From the last two compiler errors you have linked in one of your comments...

...I would conclude that Intention.UID is a nullable type int? and not a not-nullable int as you said in the comments. This indeed doesn't compile. Try to change your last query to:

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

The other three queries do not work because user.UserLocations is a collection of a non-primitive custom type in memory (for the SQL query to be generated it is a "constant" value) and EF doesn't support to build a SQL query with such a constant custom type.



来源:https://stackoverflow.com/questions/11729384/returning-a-collection-of-objects-where-an-objects-property-matches-any-property

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!