Why Where clause is not applied to IQueryable in the AddWhereToQuery function ?
It should be reference type and I cannot see why this code should not work as I expect.
[Route("/testing")]
public class MyTestController : ControllerBase
{
private readonly YieldigoDbContext _db;
public MyTestController(YieldigoDbContext db)
{
_db = db;
}
[HttpGet]
public IActionResult Get()
{
var queryable = _db.Articles.AsQueryable();
AddWhereToQuery(queryable);
var queryString = queryable.ToQueryString();
return Ok(queryString);
}
private void AddWhereToQuery(IQueryable<Article> queryable)
{
queryable = queryable.Where(x => x.Status == ArticleStatus.Active);
}
}
When I add ref keyword it works just fine, but why ref is necessary
[Route("/testing")]
public class MyTestController : ControllerBase
{
private readonly YieldigoDbContext _db;
public MyTestController(YieldigoDbContext db)
{
_db = db;
}
[HttpGet]
public IActionResult Get()
{
var queryable = _db.Articles.AsQueryable();
AddWhereToQuery(ref queryable);
var queryString = queryable.ToQueryString();
return Ok(queryString);
}
private void AddWhereToQuery(ref IQueryable<Article> queryable)
{
queryable = queryable.Where(x => x.Status == ArticleStatus.Active);
}
}
CodePudding user response:
You should change your code in this way:
[HttpGet]
public IActionResult Get()
{
var queryable = _db.Articles.AsQueryable();
queryable = AddWhereToQuery(queryable);
var queryString = queryable.ToQueryString();
return Ok(queryString);
}
private IQueryable<Article> AddWhereToQuery(IQueryable<Article> queryable)
{
return queryable.Where(x => x.Status == ArticleStatus.Active);
}
CodePudding user response:
In your Get()
method you create a variable var queryable
which we'll call 1
that contains a reference to that instance which we'll call A
. So queryable
holds a reference 1->A
.
Now you call the function AddWhereToQuery(... queryable)
. The queryable
is a copy of your variable which we'll call 2
that points to the same reference 2->A
.
So now you create a new instance of a queryable object which we'll call B
and you save that in your queryable
in the scope of the function. So now 2->B
.
As you see at no point have you changed what 1
points to so the instance with your Where
filter is never used. If you were to use ref
is won't make a copy but will pass the variable itself (whether struct or reference type).