简体   繁体   中英

How to design a common class to accept a list and dbset

I have some business logic that is used by both an api and a job manager which uses a database to store data. simplified like this:.

class BusinessLogic 
{
    public IEnumerable<Request> Requests {get;set;}

    public List<Requests> GetData()
    {
         return Requests.Where(r => r.StatusId == Constants.STATUS_NOT_PROCESSED_ID).ToList();
    }
}

class apiprocessor
{
    public void Process()
    {
        var requests = new List<Request>();

        BusinessLogic.Requests = requests;
        BusinessLogic.GetData();
    }
}

class dbprocessor
{
    private DbContext _db;

    public void Process()
    {
        //this sends the where clause to the db
        //var requests = _db.Requests.Where(r => r.StatusId == Constants.STATUS_NOT_PROCESSED_ID).ToList();

        BusinessLogic.Requests = _db.Requests;  //type DbSet<Request> Requests
        //this one doesnt
        BusinessLogic.GetData();
    }
}

functionally this works but there is a problem.

if i try and get the data using the dbcontext in the db processor the resulting query that the mysql server receives is:

SELECT
`Extent1`.`RequestID`, 
`Extent1`.`RequestType`, 
`Extent1`.`StatusId`
FROM `Requests` AS `Extent1`
 WHERE (0 = `Extent1`.`StatusId`)

(notice the WHERE clause)

when the same code is run in the BusinessLogic class above, the resulting query is:

SELECT
`Extent1`.`RequestID`, 
`Extent1`.`RequestType`, 
`Extent1`.`StatusId`
FROM `Requests` AS `Extent1`

the Where clause is missing which means that the entire table is being retrieved and then the where clause is being applied to the data in memory

is there anyway to design the common class so that when it gets called with a dbset it sends the where clause to the db?

EDIT: To be clear, IQueryable is not an option because List does not inherit from it which is what the api processor uses. However, using a List in the api processor is not mandatory

Thanks!

Try using

IQuerable<Request> Requests

instead of

IEnumerable<Request> Requests

Update: You can use a repository pattern. I use this pattern which is very lightweight and extendable.

You could use IQuerable<Request> instead of IEnumerable<Request> .

However, it is not common to have a separate BusinessLogic class just to maintain IQuerable<Request> .

Those whoever needs the data could have called straight to _db.Requests .

var result = _db.Requests
   .Where(r => r.StatusId == Constants.STATUS_NOT_PROCESSED_ID)
   .ToList()

Or, you could just create a repository layer like this to keep all logic.

If you do not like neither of above approach, you can use Specification pattern .

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