Повторное использование кода Linq to SQL с entityframework

В настоящее время я занимаюсь некоторым рефакторингом кода, который делает мое приложение очень медленным. Я довольно далеко, но мне все еще не хватает некоторых кусочков головоломки, надеюсь, вы можете мне помочь.

Мне нравится повторно использовать некоторый код Linq to SQL внутри моего проекта. Вот мой способ сделать это сейчас:

public DomainAccount GetStandardUserAccount()
{
    return  this.DomainAccounts.Where(da => da.DomainAccountType == DomainAccountType.Standarduser).First() as DomainAccount;
}

var CurrentSituation = _context.Employees.ToList().Where(e => e.GetStandardUserAccount().Username.Contains("test")).ToList();

Небольшое уточнение: у каждого сотрудника есть несколько учетных записей домена, одна из которых всегда является стандартной (DomainAccountType) domainaccount.

Поскольку Linq не может преобразовать метод C# в sqlstatement (даже если его код linq to sql только), мне нужно сначала преобразовать dbset в список, чтобы я мог использовать GetStandardUserAccount (). Этот код работает медленно из-за всего преобразования dbset. Есть ли способ повторно использовать linq для кода sql, не превращая его в метод? Я прочитал несколько тем, и вот что я получил до сих пор:

Func<Employee, DomainAccount> GetStandardDomainAccount = x => x.DomainAccounts.FirstOrDefault(d => d.DomainAccountType == DomainAccountType.Standarduser);
var TheGoal = _context.Employees.Where(e => e.GetStandardDomainAccount().Username.Contains("Something")).ToList();

Сначала вам понадобится Func, а не Expression<Func>. В любом случае вы должны передать это вызов, либо позвонив Invoke, либо просто ().

HimBromBeere 05.12.2018 09:44

1) Если эти лямбды переводятся в SQL (предположим, что это из-за переменной _context), то, по крайней мере, у вас есть проблема с запросом: string.Contains приводит к LIKE '%whatever%', который, в свою очередь, не использует индексы. 2) as без проверки на нуль - это путь к NRE. Если что-то должно бытьDomainAccount, то приведите это явно. Если это возможноDomainAccount, и это нормально, когда это не являетсяDomainAccount, то используйте as с последующей проверкой нуля.

Dennis 05.12.2018 10:08

1) linq будет переведен в sql, но string.contains всегда работает для меня (см. Текущее решение). 2) Я не уверен, что мне делать с этим отзывом. В методе C# используется 'as', но следует ли мне использовать его и в моем func <>?

Pieter 05.12.2018 10:43

@Pieter Я удалил свой ответ, так как он бесполезен для Linq2Entities.

HimBromBeere 05.12.2018 10:53
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
4
126
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ответ на этот вопрос немного сложнее, чем кажется. Чтобы позволить linq выполнять код C#, вам нужно сделать функцию выражением, чтобы входные и выходные данные интерпретировались не как код, а как какое-то значение. Решение выглядит так:

 private Expression<Func<TPeople, bool>> GetDefaultDomainAccount<TPeople>(Func<DomainAccount, bool> f) where TPeople : Person
        {
            return (a) => f(a.DomainAccounts.FirstOrDefault(d => d.DomainAccountType == DomainAccountType.Standarduser));
        }

Теперь код можно вызвать следующим образом:

    public IQueryable<TPeople> GetPeopleByUsername<TPeople>(string username) where TPeople : Person
    {
        GetPeople<TPeople>().Where(GetDefaultDomainAccount<TPeople>(d => d.Username == username));
        return people;
    }

вместо этого:

        public IQueryable<TPeople> GetPeopleByUsername<TPeople>(string username) where TPeople : Person
    {
        username = username.ToUpper();
        var people = GetPeople<TPeople>()
            .Where(a => a.DomainAccounts.FirstOrDefault(d => d.DomainAccountType == DomainAccountType.Standarduser).Username.ToUpper().Contains(username));

        return people;
    }

Это полезно

JulyOrdinary 05.02.2019 14:26

Другие вопросы по теме