0

I have a filter class structure like this

public class SchemeInvestorDataDateFilter
{
    public int SchemeId { get; set; }
    public int InvestorId { get; set; }
    public DateTime Date { get; set; }
}

I am passing the list of this filter object to get the data from database using linq like this

var schemeIds = filters.Select(x => x.SchemeId);
var investorIds = filters.Select(x => x.InvestorId);
var dates = filters.Select(x => x.Date);

var query = Context.SchemeInvestorDataDates
        .Where(x =>
        schemeIds.Contains(x.SchemeInvestor.SchemeId) &&
        investorIds.Contains(x.SchemeInvestor.InvestorId) &&
        dates.Contains(x.Date) &&
        !x.IsDeleted
        );

Everything is working fine but this is not the correct way to do of what I exactly want.

I want it to filter the rows for the combination of schemeId + investorId + date

So basically it should return the rows which has this combination matching.

Currently it returns the rows of all permutation combination of passed schemeId, investorId and date.

This works because it returns all the records which suffice my condition but it is not the right way because it is returning some extra rows also which I do not want.

But I am not sure how can I write a query in link that checks this combination of in memory filter list for each DB Entity.

I know how to do it with Dapper but I am looking for a way using linq.

Is there a way even exist?

EDIT

This how this can be achieved using dapper. (Similar case as the above one)

StringBuilder query = new StringBuilder("select * from schemeinvestors si join (");

for (int i = 0; i < schemeInvestorIds.Count(); i++)
{
    var data = schemeInvestorIds.ElementAt(i);
    query.Append($"select {data.investorId} as InvestorId, {data.schemeId} as SchemeId");
    query.Append(schemeInvestorIds.Count() - 1 == i ? "" : " union ");
}

query.Append(") x on si.InvestorId=x.InvestorId and si.SchemeId=x.SchemeId");

using (var connection = BuildConnection())
{
    connection.Open();

    return await connection.QueryAsync<SchemeInvestor>(query.ToString());
}
4
  • @YongShun - Updated the question of how it can be achieved using dapper Commented Sep 8, 2024 at 9:21
  • Think that it is not possible to join the DB entities with in-memory collection, you have to query the DB entities into the memory then perform joining with the filters. Commented Sep 8, 2024 at 9:30
  • Check this extension Commented Sep 8, 2024 at 12:46
  • You may need to use a loop together with PredicateBuilder to build out your conditions and effectively get .Where(x => (x.SchemeInvestor.SchemaId == filters[0].SchemaId && x.SchemeInvestor.InvestorId == filters[0].InvestorId && x.Date == filters[0].Date) || (...same for [1]...) || ... (...same for [last]...)). For each filter entry, you would build an inner predicate using .And() and then use those predicates to build an outer predicate using .Or(). Commented Sep 8, 2024 at 19:12

1 Answer 1

0

Could you check every SchemeInvestorDataDates against each value in your Filters?

var query = Context.SchemeInvestorDataDates
                   .Where(x => filters.Any(filter =>
                                   filter.SchemeId == x.SchemeInvestor.SchemeId &&
                                   filter.InvestorId == x.SchemeInvestor.InvestorId &&
                                   filter.Date == x.Date) &&
                               !x.IsDeleted);
Sign up to request clarification or add additional context in comments.

2 Comments

This doesn't work. Throws runtime exception. It cannot translate this query to sql query.
Check filters.AsQueryable().Any(, it should work with newest EF Core, but I'm not sure.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.