How to execute stored procedure with input and output parameters using EF?

前端 未结 3 592
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-11 08:51

I am using EF code first approach and I have created stored procedure using migration as following:

public override void Up()
    {
        Sql(@\"CREATE TYP         


        
相关标签:
3条回答
  • 2020-12-11 09:24

    I have solved it this way.

    First of all I have updated my stored procedure to return Ids as following:

     public override void Up()
        {
            Sql(@"CREATE TYPE IdsList AS TABLE   
                        ( 
                        Id Int
                        )
                        GO
    
                        Create Procedure getChildIds(
                        @IdsList dbo.IdsList ReadOnly
                        )
                        As
                        Begin
                        WITH RecursiveCTE AS
                        (
                            SELECT Id
                            FROM dbo.PhysicalObjects
                            WHERE ParentId in (Select * from @IdsList)
                            UNION ALL
    
                            SELECT t.Id
                            FROM dbo.PhysicalObjects t
                            INNER JOIN RecursiveCTE cte ON t.ParentId = cte.Id
                        )
                        SELECT Id From RecursiveCTE
                        End");
        }
    
        public override void Down()
        {
            Sql(@" Drop Procedure getChildIds
                   Go
                   Drop Type IdsList
                   ");
        }
    

    And here how I have solved executing stored procedure using entity framework:

     var dataTable = new DataTable();
     dataTable.TableName = "idsList";
     dataTable.Columns.Add("Id", typeof(int));
     dataTable.Rows.Add(1);
     dataTable.Rows.Add(2);
    
      SqlParameter idsList = new SqlParameter("idsList", SqlDbType.Structured);
      idsList.TypeName = dataTable.TableName;
      idsList.Value = dataTable;
    
      var results = dbContext.Database.SqlQuery<int>("exec getChildIds @idsList", idsList).ToList();
    

    I hope my code will help others having the same issue

    0 讨论(0)
  • 2020-12-11 09:29

    You will have to obtain your data a different way:

    You cannot return data in a table-valued parameter. Table-valued parameters are input-only; the OUTPUT keyword is not supported.

    0 讨论(0)
  • 2020-12-11 09:44

    The best solution for using user's procedures/functions and build-in functions in SQL is this library - https://github.com/Dixin/EntityFramework.Functions

    It has great and easy implementation. Also it allows to follow code first approach

    In your case you need to use Table-valued function

    Define model

    [ComplexType]
    public class IdModel
    {
         public int Id { get; set; }
    }
    

    Declare Type and Convention in DbContext

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Add(new FunctionConvention<DbContext>());
    
        modelBuilder.ComplexType<IdModel>();
    
        base.OnModelCreating(modelBuilder);
    }
    

    Define function in DbContext

    [Function(FunctionType.TableValuedFunction, nameof(ufnGetChildIds), Schema = "dbo")]
    public IQueryable<IdModel> ufnGetChildIds([Parameter(DbType = "IdModel", Name = "IdsList")]List<IdModel> IdsList)
    {
        ObjectParameter IdsListParameter = new ObjectParameter("IdsList", IdsList);
    
        return this.ObjectContext().CreateQuery<IdModel>(
            $"[{nameof(this.ufnGetChildIds)}](@{nameof(IdsList)})", IdsListParameter);
    }
    

    And use it from your DbContext

    [TestMethod]
    public void CallTableValuedFunction()
    {
        using (DbContext database = new DbContext())
        {
            IQueryable<IdModel> employees = database.ufnGetChildIds(new List<IdModel> { new IdModel { Id = 1 }});
        }
    }
    
    0 讨论(0)
提交回复
热议问题