通过实体框架重用Linq转换为SQL代码

时间:2018-12-05 08:42:40

标签: c# sql entity-framework linq lambda

我目前正在对代码进行一些重构,这使我的应用程序非常慢。我已经很遥远了,但我仍然缺少一些难题,希望您能为我提供帮助。

我喜欢在项目内部重用一些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)域帐户。

因为Linq无法将C#方法转换为sqlstatement(仅将其linq转换为sql代码),所以我必须首先将dbset转换为列表,以便可以使用GetStandardUserAccount()。由于整个dbset转换,此代码很慢。有没有一种方法可以重用linq到sql代码而无需在methode中打开它?我已经读了一些主题,这是我直到现在所得到的:

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();

1 个答案:

答案 0 :(得分:2)

这个问题的答案比看起来要复杂一些。为了使linq执行C#代码,您需要使该函数成为表达式,以便in和输出将不作为代码而是作为某种含义被插入。解决方案如下:

 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));
        }

现在代码可以像这样被称为uppon:

    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;
    }