Table Valued Function and Entity Framework

前端 未结 3 1328
生来不讨喜
生来不讨喜 2021-02-05 13:28

I\'m trying to execute an TVF with Entity Framework and for some reason it just doesn\'t work. Maybe anyone out there can help me see the problem.

Here are the code samp

相关标签:
3条回答
  • 2021-02-05 13:53

    Here is a very good article on the newer features of Entity Framework that provide direct support for Table Valued UDFs. MSDN blog on Table-Valued Function Support in Entity Framework.

    For greater depth, this article provides significant detail. EDM and store functions exposed in LINQ.

    One of the great advantages of the recent support for Table-Valued UDFs involves support for Full-Text Search capabilities. Read more about that here: Full text search features involving database objects.

    0 讨论(0)
  • 2021-02-05 14:07

    [Tested] using:

    Install-Package EntityFramework.CodeFirstStoreFunctions
    

    Declare a class for output result:

    public class MyCustomObject
    {
       [Key]
       public int Id { get; set; }
       public int Rank { get; set; }
    }
    

    Create a method in your DbContext class

    [DbFunction("MyContextType", "SearchSomething")]
    public virtual IQueryable<MyCustomObject> SearchSomething(string keywords)
    {
       var keywordsParam = new ObjectParameter("keywords", typeof(string)) 
                               { 
                                  Value = keywords 
                                };
        return (this as IObjectContextAdapter).ObjectContext
        .CreateQuery<MyCustomObject>(
         "MyContextType.SearchSomething(@keywords)", keywordsParam);
    }
    

    Add

    public DbSet<MyCustomObject> SearchResults { get; set; }
    

    to your DbContext class

    Add in the overriden OnModelCreating method:

    modelBuilder.Conventions
    .Add(new CodeFirstStoreFunctions.FunctionsConvention<MyContextType>("dbo"));
    

    And now you can call/join with a table values function like this:

    CREATE FUNCTION SearchSomething
    (   
        @keywords nvarchar(4000)
    )
    RETURNS TABLE 
    AS
    RETURN 
    (SELECT KEY_TBL.RANK AS Rank, Id
    FROM MyTable 
    LEFT JOIN freetexttable(MyTable , ([MyColumn1],[MyColumn2]), @keywords) AS KEY_TBL      
    ON MyTable.Id = KEY_TBL.[KEY]  
    WHERE KEY_TBL.RANK > 0   
    )
    GO
    
    0 讨论(0)
  • 2021-02-05 14:09

    This is a way to send table parameter to function and return values of table valued function.

    C#:

    var fooDataTable = new DataTable();
    var ids = new List<FooDto>();
    if (ids.Count > 0)
    {
        fooDataTable.Columns.Add("ID", typeof(int));
        fooDataTable.Columns.Add("CarNumber");
        fooDataTable.Columns.Add("ArriveDate", typeof(DateTime));                
    
        foreach (var car in ids)
        {
            fooDataTable.Rows.Add(car?.ID, car?.CarNumber, car?.ArriveDate);
        }
    }
    
    SqlParameter cdIDs = new SqlParameter("@ListToCalc", SqlDbType.Structured);
    cdIDs.Value = fooDataTable;
    cdIDs.TypeName = "tp_CarList";
    
    var template = new CarFieldsDTO
    {
        Fields = db.Database.SqlQuery<fn_Car_Result>
            ("SELECT * FROM dbo.fn_Car(@ListToCalc)", cdIDs)
                .Select(field => new CarFieldsDTO
                {
                    ID = field.ID,
                    CarNumber = field.CarNumber,
                    ArriveDate = field.ArriveDate,                    
                }).ToList()
    };
    
    var fields = new List<CarFieldsDTO> { template };
    return fields.AsQueryable();
    

    Where db is DbContext.

    DTO:

    public class CarFieldsDTO
    {        
        public int ID { get; set; }
    
        public string CarNumber { get; set; }
    
        public DateTime? ArriveDate { get; set; }
    
        public IEnumerable<CarFieldsDTO> Fields { get; set; }
    }
    

    SQL table valued function:

    ALTER  FUNCTION [dbo].[fn_Car]
    (
          @ListToCalc tp_CarList READONLY
    )
    RETURNS TABLE
    AS
        RETURN
        (
            SELECT l.ID
                   , l.CarNumber
                   , l.ArriveDate
            FROM @ListToCalc l
            INNER JOIN Stations as sf ON sf.ID = l.id_StationFrom
        )
    

    User defined Table Type:

    CREATE TYPE [dbo].[tp_CarList] AS TABLE(
        [ID] [int] NOT NULL,
        [CarNumber] [varchar](12) NULL,
        [ArriveDate] [datetime] NULL    
    )
    GO
    
    0 讨论(0)
提交回复
热议问题