user2515186
user2515186

Reputation: 2157

Unable to create a constant value of type Only primitive types or enumeration types are supported in this context

I am getting this error for the query below

Unable to create a constant value of type API.Models.PersonProtocol. Only primitive types or enumeration types are supported in this context

ppCombined below is an IEnumerable object of PersonProtocolType, which is constructed by concat of 2 PersonProtocol lists.

Why is this failing? Can't we use LINQ JOIN clause inside of SELECT of a JOIN?

var persons = db.Favorites
    .Where(x => x.userId == userId)
    .Join(db.Person, x => x.personId, y => y.personId, (x, y) =>
        new PersonDTO
        {
            personId = y.personId,
            addressId = y.addressId,                   
            favoriteId = x.favoriteId,
            personProtocol = (ICollection<PersonProtocol>) ppCombined
                .Where(a => a.personId == x.personId)
                .Select( b => new PersonProtocol()
                 {
                     personProtocolId = b.personProtocolId,
                     activateDt = b.activateDt,
                     personId = b.personId
                 })
        });

Upvotes: 197

Views: 265458

Answers (6)

ebrahim.mr
ebrahim.mr

Reputation: 719

I had this issue and what I did and solved the problem was that I used AsEnumerable() just before my Join clause. here is my query:

List<AccountViewModel> selectedAccounts;

 using (ctx = SmallContext.GetInstance()) {
                var data = ctx.Transactions.
                    Include(x => x.Source).
                    Include(x => x.Relation).
                    AsEnumerable().
                    Join(selectedAccounts, x => x.Source.Id, y => y.Id, (x, y) => x).
                    GroupBy(x => new { Id = x.Relation.Id, Name = x.Relation.Name }).
                    ToList();
            }

I was wondering why this issue happens, and now I think It is because after you make a query via LINQ, the result will be in memory and not loaded into objects, I don't know what that state is but they are in in some transitional state I think. Then when you use AsEnumerable() or ToList(), etc, you are placing them into physical memory objects and the issue is resolving.

Upvotes: 2

James Perih
James Perih

Reputation: 1384

It's worth adding, since the OP's code sample doesn't provide enough context to prove otherwise, but I received this error as well on the following code:

public RetailSale GetByRefersToRetailSaleId(Int32 refersToRetailSaleId)
{
    return GetQueryable()
        .FirstOrDefault(x => x.RefersToRetailSaleId.Equals(refersToRetailSaleId));
}

Apparently, I cannot use Int32.Equals in this context to compare an Int32 with a primitive int; I had to (safely) change to this:

public RetailSale GetByRefersToRetailSaleId(Int32 refersToRetailSaleId)
{
    return GetQueryable()
      .FirstOrDefault(x => x.RefersToRetailSaleId == refersToRetailSaleId);
}

Upvotes: 1

khaled saleh
khaled saleh

Reputation: 518

Just add AsEnumerable() andToList() , so it looks like this

db.Favorites
    .Where(x => x.userId == userId)
    .Join(db.Person, x => x.personId, y => y.personId, (x, y).ToList().AsEnumerable()

ToList().AsEnumerable()

Upvotes: 0

Colin
Colin

Reputation: 1846

In my case, I was able to resolve the issue by doing the following:

I changed my code from this:

var r2 = db.Instances.Where(x => x.Player1 == inputViewModel.InstanceList.FirstOrDefault().Player2 && x.Player2 == inputViewModel.InstanceList.FirstOrDefault().Player1).ToList();

To this:

var p1 = inputViewModel.InstanceList.FirstOrDefault().Player1;
var p2 = inputViewModel.InstanceList.FirstOrDefault().Player2;
var r1 = db.Instances.Where(x => x.Player1 == p1 && x.Player2 == p2).ToList();

Upvotes: 5

Roelant
Roelant

Reputation: 65

Don't know if anyone searches for this. I had the same problem. A select on the query and then doing the where (or join) and using the select variable solved the problem for me. (problem was in the collection "Reintegraties" for me)

query.Select(zv => new
            {
                zv,
                rId = zv.this.Reintegraties.FirstOrDefault().Id
            })
            .Where(x => !db.Taken.Any(t => t.HoortBijEntiteitId == x.rId
                                             && t.HoortBijEntiteitType == EntiteitType.Reintegratie
                                             && t.Type == TaakType))
            .Select(x => x.zv);

hope this helps anyone.

Upvotes: 2

Slauma
Slauma

Reputation: 177163

This cannot work because ppCombined is a collection of objects in memory and you cannot join a set of data in the database with another set of data that is in memory. You can try instead to extract the filtered items personProtocol of the ppCombined collection in memory after you have retrieved the other properties from the database:

var persons = db.Favorites
    .Where(f => f.userId == userId)
    .Join(db.Person, f => f.personId, p => p.personId, (f, p) =>
        new // anonymous object
        {
            personId = p.personId,
            addressId = p.addressId,   
            favoriteId = f.favoriteId,
        })
    .AsEnumerable() // database query ends here, the rest is a query in memory
    .Select(x =>
        new PersonDTO
        {
            personId = x.personId,
            addressId = x.addressId,   
            favoriteId = x.favoriteId,
            personProtocol = ppCombined
                .Where(p => p.personId == x.personId)
                .Select(p => new PersonProtocol
                {
                    personProtocolId = p.personProtocolId,
                    activateDt = p.activateDt,
                    personId = p.personId
                })
                .ToList()
        });

Upvotes: 280

Related Questions