简体   繁体   中英

Avoid client evaluation while maintain clean code in EF Core 3

I need to write more complicated queries to my database. It is easily possible to maintain clean code with client evaluation on, but I am dealing with a lot of data and need to keep my backend quick.

Customer entity is nice example of it. This is how my query looks like now:

public class CustomerFilter : AbstractProjectFilter
{
    public CustomerFilter(string query, bool includeNotSet, ICollection<string> customers) :
        base(e => (customers == null)
                  || (includeNotSet && e.Customer == null)
                  || (customers.Contains("Company") && e.Customer.Type == CustomerType.Company &&
                      EF.Functions.Like((((CustomerCompany)e.Customer).Name + " " + ((CustomerCompany)e.Customer).Crn + " " + ((CustomerCompany)e.Customer).VatRegNo), "%" + query + "%"))
                  || (customers.Contains("Person") && e.Customer.Type == CustomerType.Person &&
                      EF.Functions.Like(((CustomerPerson)e.Customer).Forename + " " + ((CustomerPerson)e.Customer).Surname, "%" + query + "%"))
                  || (customers.Contains("Evidence") && e.Customer.Type == CustomerType.InEvidence &&
                      EF.Functions.Like(e.Customer.EvidenceName, "%" + query + "%"))
        )
    {
    }
}

With client evaluation on, this would be much cleaner, because I would be able to use this method to create name string based on customer derived type with extension method (I am intentionally avoiding virtual methods) like this and use it to make my query short and clean:

public static string NameString(this Customer customer)
    {
        if (customer.IsObjectNull())
            return string.Empty;

        return customer.Type switch
        {
            CustomerType.InEvidence => ((CustomerInEvidence) customer).EvidenceName,
            CustomerType.Person => (((CustomerPerson) customer).Forename + " " +
                                    ((CustomerPerson) customer).Surname),
            CustomerType.Company => ((CustomerCompany) customer).Name,
            _ => throw new ArgumentOutOfRangeException()
        };
    }

My question: Is there a way to tell the database how to handle methods without the need to fetch data from it? Some configuration of Fluent API I am missing?

It would also be nice if I would be able to use these "methods" during sorting with Linq.Dynamic like this:

var orderedCustomers = await customers.OrderBy("*string_created_by_some_method* ASC").ToListAsync();

Is there a way to tell the database how to handle methods without the need to fetch data from it? Some configuration of Fluent API I am missing?

There isn't any straightforward way, this way is exactly what Expression is!

The only way that you can talk to database without fetching data is using Expressions . it is not very straight but can do everything that you need.

You can see one example of it here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM