우리가 직접 만든 SQL을 호출하게 하는 기능이다. 연산을 DB쪽에서 하도록 떠넘기고 싶을 때 사용한다. 또 EF Core 쪽에서 비효율적인 쿼리를 짤 수 있을 때 우리가 직접 정의할 수 있다.
SQL 쿼리를 만든 후 DB에 등록하고 등록한 함수를 호출하도록 하자
static 함수를 만들고 EF Core에 등록
 public class ItemReview
    {
        public int ItemReviewId { get; set; }
        public int Score { get; set; }
    }
    [Table("Item")]
    public class Item
    {
    	...
    
        public ICollection<ItemReview> Reviews { get; set; }
    }
    	
  [DbFunction()] // UDF로 인식
        public static double? GetAverageReviewScore(int itemId)
        {
            throw new NotImplementedException("C#에서 사용금지!");
        }
강의에서는 클래스를 따로 만들지 않고, 그냥 Program 클래스 안에 static 함수를 정의하였다. C# 코드에서 호출되면 바로 Exception을 날리도록 정의했고, [DbFunction()]을 삽입하여 UDF로 인식되게 하였다. Fluent API로도 UDF로 인식하게 할 수는 있으나 어노테이션 방식이 더 깔끔하다.
 builder.HasDbFunction(() => Program.GetAverageReviewScore(0)); // 아무값이나 인자로
cmd 문자열에 함수 몸체를 다음과 같이 SQL 구문을 정의한다.
// Database Setup
                string cmd = @"CREATE FUNCTION GetAverageReviewScore (@itemId INT) RETURNS FLOAT
                                AS
                                BEGIN
                                
                                DECLARE @result AS FLOAT
                                
                                SELECT @result = AVG(CAST([Score] AS FLOAT))
                                FROM ItemReview AS r
                                WHERE @itemId = r.ItemId
                                RETURN @result
                                END
                                ";
                db.Database.ExecuteSqlRaw(cmd);
			...
            items[0].Reviews = new List<ItemReview>()
            {
                new ItemReview() { Score = 5 },
                new ItemReview() { Score = 3 },
                new ItemReview() { Score = 1 },
            };
            
            ...
            
        public static void CalcAverage()
        {
            using (AppDbContext db = new AppDbContext())
            {
                foreach (var avg in db.Items.Select(i => Program.GetAverageReviewScore(i.ItemId)))
                {
                    if(avg == null)
                        Console.WriteLine("리뷰 없음");
                    else
                        Console.WriteLine($"Avg : {avg.Value}");
                }
            }
        }