Reputation: 91
I am trying to call a scalar function that I have in my database from my .NET Core 2.1 Web API to get an employee's director; the function in my database expects the employee id as input, and returns the id of the director. It works just fine and is called dbo.fn_GetDirectorID
.
I wanted to make an endpoint in my Web API to call this function get the directorID
then send back the employee object of that director to my client. So I was looking for online resources and I came across this I was like wow it's possible so let's try it out so I followed their tutorial I now have a GetDirectorID
database function in my context like the link described
[DbFunction("fn_GetDirectorID", "dbo")]
public static int GetDirectorID(int id)
{
throw new NotImplementedException();
}
Then in my controller I was going to do something like this
[HttpGet("GetDirector/{id}")]
public async Task<IActionResult> GetDirector([FromRoute] int id)
{
var directorID = KPContext.GetDirectorID(id);
var director = await _context.Employees.FindAsync(directorID);
if (director == null)
{
return NotFound();
}
return Ok(director);
}
but when I call the I throw the error because I get to the throw new NotIMplementedException
, but I am not sure what to do here because the tutorial is saying this should call your function and work. Also I did do
int directorID = KPContext.GetDirectorID(id)
Can anyone help? I would greatly appreciate it.
I also just tried this
[HttpGet("GetDirector/{id}")]
public async Task<IActionResult> GetDirector([FromRoute] int id)
{
var director = await _context.Employees.FindAsync(KPContext.GetDirectorID(id));
if (director == null )
{
return NotFound();
}
return Ok(director);
}
Upvotes: 2
Views: 375
Reputation: 205719
Scalar functions like this can only be used inside LINQ to Entities query (cannot be executed client side, must be a part of SQL query).
Which means you cannot use FindAsync
, so use FirstOrDefaultAsync
or SingleOrDefaultAsync
instead:
var director = await _context.Employees
.SingleOrDefaultAsync(e => e.Id == KPContext.GetDirectorID(id));
This also has advantage over FindAsync
that you can eager load (Include
/ ThenInclude
) related data if you have such.
Also please note (not mentioned in the link) that if the scalar function is defined in a class other than the target DbContext
derived class, it won't be registered automatically, so you'll need to add something like this to your DbContext
derived class OnModelCreating
override (if it's not the KPContext
class of course):
modelBuilder.HasDbFunction(() => KPContext.GetDirectorID(default(int)));
For more info, see Database scalar function mapping documentation.
Upvotes: 4
Reputation: 398
I would try a linq query because I don't think pure EF is supported yet.
[HttpGet("GetDirector/{id}")]
public async Task<IActionResult> GetDirector([FromRoute] int id)
{
var director = from p in _context.Employees where p.EmployeeId == KPContext.GetDirectorID(id) select p;
if (director == null )
{
return NotFound();
}
return Ok(director);
}
this should get you what you need let me know if it works for you!! cheers and have a good day.
Upvotes: 1