NOT IN in Inline using a sub-query

Asked

Viewed 1,579 times

1

I am using as a basis the answer in: https://stackoverflow.com/questions/432954/not-in-clause-in-linq-to-entities

I need to make a query where do not contain (NOT IN) the Ids coming from another query.

The SQL Query is this:

SELECT DISTINCT tbl_boleto.int_IDC, tbl_Admin.* //redução do código
FROM            tbl_boleto INNER JOIN
                         tbl_Admin ON tbl_boleto.int_IDC = tbl_Admin.intid
WHERE        (tbl_boleto.int_IDC NOT IN
                             (SELECT DISTINCT int_IDC
                               FROM            tbl_boleto 
                               WHERE        (sdt_DataReferencia = '20160401'))) AND (tbl_Admin.int_STATUS IN (4, 5))
ORDER BY tbl_Admin.int_STATUS, tbl_Admin.str_URL

I’m trying to:

    var condicaoStatus = new[] { 4, 5 };
    var IdClientesSemBoleto = (from cli in db.Clientes
                             join bol in db.Boletos on cli.ClienteId equals bol.ClienteId
                             where bol.DataReferencia == DataRef && condicaoStatus.Contains(cli.Status)
                             select new {IDC = cli.ClienteId });

        var clientes = db.Boletos
            .Include(i => i.Cliente)
            .Select(s => s.ClienteId)
             .Where(s => !IdClientesSemBoleto.Contains(s.ClienteId));

But the line:

 .Where(s => !IdClientesSemBoleto.Contains(s.ClienteId));

Of error:

Error CS1061 'int' does not contain a Definition for 'Clienteid' and no Extension method 'Clienteid' Accepting a first argument of type 'int' could be found (are you Missing a using Directive or an Assembly Reference?)

What am I doing wrong?

How to do it? There is a better way to be done than this solution of mine?

  • Then problem ta at the return of the Linq Idclientssemboleto it returns an object not an id just sees if it can access Idclientssemboleto.ClienteId.Contains(s. Clienteid)

2 answers

3


In doing select new {IDC = cli.ClienteId } the content of IdClientesSemBoleto is a list of an anonymous type, which only contains the property IDC. You don’t need the creation of this kind, one can just do select cli.ClienteId. This will make it IdClientesSemBoleto be a list of int's, which will facilitate the select below.

This code snippet

var clientes = db.Boletos
    .Include(i => i.Cliente)
    .Select(s => s.ClienteId)
    .Where(s => !IdClientesSemBoleto.Contains(s.ClienteId));

Switch to

var clientes = db.Boletos
    .Include(i => i.Cliente)
    .Where(s => !IdClientesSemBoleto.Contains(s.ClienteId))
    .Select(s => s.ClienteId);
  • worked, but in the first query where I have a list id is bringing repeat ids, because in the final result brought 15 records and in my query with Distinct brought 1, the 15 results are identical

  • Well, then the problem is with the logic of your query. It would be the case to open a new question, because the problem is different from this one.

  • Actually I don’t think so, because in my example query you have the distinct... tried... select cli.Clienteid ).Distinct(); but it still hasn’t... test

  • @jbueno did not know that anonymous types caused error as well, what I thought was the solution was only the solution of half of the problem. Thank you for the information!

  • 2

    @Thiagoferreira Actually, they do not give error no. You can adapt select to work with a type too, would not have problem. But this is completely wordy, if you only need a list of integers, make it return a list of integers, not a list of objects. It’s like using a pistol to kill a fly =)

  • 1

    @Dorathoto still think you should open a new question to solve the distinct problem. But if you want a tip, basically you can make a group by ClienteId and return the first group element...

  • I made a Ienumerable<boleto> filteredList = clients . Groupby(Customer => Customer.Clienteid) . Select(group => group.Firstordefault()). Tolist(); and then gave the distinct...I will ask a new question

Show 2 more comments

1

The problem in the order in which you are doing things. First, in this line:

.Select(s => s.ClienteId)

Here you are turning your entire LINQ query into a IEnumerable<int>, because you are selecting only the ClienteId

So, on this line:

.Where(s => !IdClientesSemBoleto.Contains(s.ClienteId));

The s does not contain property ClienteId because the very s is the ClienteId! It is the integer you selected in the previous row.

So there are two ways to solve your problem:

Change the order of your query thus:

var clientes = db.Boletos
    .Include(i => i.Cliente)
    .Where(s => !IdClientesSemBoleto.Contains(s.ClienteId));
    .Select(s => s.ClienteId)

Or keep the query the way it is, only making changes in the Where():

var clientes = db.Boletos
    .Include(i => i.Cliente)
    .Select(s => s.ClienteId)
    .Where(s => !IdClientesSemBoleto.Contains(s));
  • 1

    I don’t think it’s right. By making a select new an anonymous type is created. This will only work if it removes the new and create a list of integers.

  • True, I hadn’t noticed that he was creating an anonymous guy. But the very Exception he posted shows that at runtime he tried to convert to the type int, then it’s likely to work.

  • Sorry @Thiagoferreira for my ignorance but it didn’t work, I tried it and the error in Where(s => !Idclientessemboleto.Contains(s); and in the first way you passed the error: 'Iqueryable<<Anonymous type: int Clienteid>>' does not contain a Definition for 'Contains' and the best Extension method Overload 'Parallelenumerable.Contains<int>(Parallelquery<int>, int)' requires a receiver of type 'Parallelquery<int>' WMB.Extranet

  • @jbueno tried to remove the new from the first select but from the error.

  • so it even ran but it lacks the distinct

Browser other questions tagged

You are not signed in. Login or sign up in order to post.