Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the recommended practice for sharing similar linq to entities expression logic in different repositories

When using the repository pattern , sometimes you have the same logic that appears in different repositories.In the example below GetTempEmployees() in EmployeeRepository and GetCompaniesWithTemps() in CompanyRepository have the same expressions

e.IsTemp && e.IsDeleted == false

My question is what is the recommended practice for minimizing this duplication of expression logic.

eg.

public class Employee
{
    public int EmployeeId { get; set; }
    public bool IsTemp { get; set; }
    public bool IsDeleted { get; set; }
}

public class Company
{
    public int CompanyId { get; set; }
    public bool IsDeleted { get; set; }
    public virtual ICollection<Employee> Employees { get; set; } 

}

public class TestContext : DbContext
{
    public TestContext()
    {
    }
    public DbSet<Employee> Employee { get; set; }
    public DbSet<Company> Company { get; set; }
}


public class EmployeeRepository
{
    private readonly TestContext _context;
    EmployeeRepository(TestContext context)
    {
        _context = context;
    }

    public ICollection<Employee> GetTempEmployees()
    {
        return _context.Employee.Where(e => e.IsTemp && e.IsDeleted==false).ToList();
    }
}

public class CompanyRepository
{
    private readonly TestContext _context;
    CompanyRepository(TestContext context)
    {
        _context = context;
    }

    public ICollection<Company> GetCompaniesWithTemps()
    {
        return _context.Company.Where(c => c.Employees.Any(e => e.IsTemp && e.IsDeleted == false)).ToList();
    }
}
like image 851
kwiri Avatar asked Dec 10 '25 14:12

kwiri


2 Answers

The solution proposed by Rawling will work. Another solution would be to provide extensions working over IQueryables. Something like:

static class PersonSetExtensions
{
    public static IQueryable<Person> WhereTempAndNotDeleted(this IQueryable<Person> set)
    {
        return set.Where(x => x.IsTemp && !x.IsDeleted);
    }
}

Which can be used in your code as:

return _context.Employee
               .WhereTempAndNotDeleted()
               .ToList();
like image 198
Polity Avatar answered Dec 13 '25 05:12

Polity


I believe you have to use an Expression, e.g.

static class EmployeeExpressions
{
    public static System.Linq.Expressions.Expression<Func<Employee, bool>>
        IsTempAndNotDeleted = e => e.IsTemp && !e.IsDeleted;
}

You can then use it as

...
return _context.Employee
    .Where(EmployeeExpressions.IsTempAndNotDeleted)
    .ToList();

...
return _context.Company
    .Where(c => c.Employees.Any(EmployeeExpressions.IsTempAndNotDeleted))
    .ToList();

but I'm a little hazy on this, so give it a try and see if it works.

like image 24
Rawling Avatar answered Dec 13 '25 03:12

Rawling



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!