实体框架/ Web API:如何返回多个存储过程调用的组合结果?

时间:2015-08-04 23:25:09

标签: c# entity-framework stored-procedures asp.net-web-api

好的,我知道我的问题可能听起来像以前被问了很多次,但这有点不同。至少我找不到同样的问题(但很多相似但不完全相同的问题)。

我不是问如何使用存储过程调用的多个结果,也不知道如何调用多个存储过程。

我想知道的是... 如何多次调用存储过程,合并每次调用的结果,并将组合结果返回到Entity Framework / Web API?

===

(以下是有关我想做什么,为什么要这样做,我尝试过的内容以及代码示例的详细信息)

我有一个OData Web服务,它有一个函数(动作),它调用一个存储过程。由于Web服务调用是一项相对昂贵的操作,我希望允许用户进行一次Web服务调用,这将为用户多次调用存储过程并返回(组合)结果。

这是我的Controller类中的一个函数,用于单个存储过程调用方案的单个Web服务调用。它运作得很好。

    public IHttpActionResult GetMorgagetDetail(ODataActionParameters parameters)
    {
        // Set up the parameters for the stored procedure
        SqlParameter[] sqlparams;
        sqlparams = new SqlParameter[2];

        sqlparams[0] = new SqlParameter("@Name", System.Data.SqlDbType.Char, 10);
        sqlparams[0].Value = parameters["Name"].ToString();

        sqlparams[1] = new SqlParameter("@Address", System.Data.SqlDbType.VarChar, 100);
        sqlparams[1].Value = parameters["Address"].ToString();

        // Call the stored procedure
        var result = this.context.Database.SqlQuery<Entities.MortgateDetail>("dbo.sp_GetMortgageDetail @Name, @Address", sqlparams);

        return Ok(result);
    }

就像我说的那样,我想让用户在其中一个参数(本例中为Address)中传递多个值,并让Web服务函数调用相同的存储过程,但多次使用不同的地址每次通话的价值。这是我尝试过的一个实现,我遇到了一个问题:

    public IHttpActionResult GetMultipleMorgagetDetail(ODataActionParameters parameters)
    {
        var response = new List<Entities.MortgateDetail>();

        // Set up the parameters for the stored procedure
        SqlParameter[] sqlparams;
        sqlparams = new SqlParameter[2];

        sqlparams[0] = new SqlParameter("@Name", System.Data.SqlDbType.Char, 10);
        sqlparams[0].Value = parameters["Name"].ToString();

        sqlparams[1] = new SqlParameter("@Address", System.Data.SqlDbType.VarChar, 100);

        var addresses = parameters["Addresses"] as IEnumerable<string>;
        foreach (string address in addresses)
        {
            sqlparams[1].Value = address;
            var result = this.context.Database.SqlQuery<Entities.MortgateDetail>("dbo.sp_GetMortgageDetail @Name, @Address", sqlparams);

            response.Add(result.FirstOrDefault<Entities.MortgateDetail>());
        }

        return Ok(response);
    }

我要做的是从返回的结果中获取单行(First或Default - sp将始终只返回一行),并将其添加到我创建的List中(类型) Entities.MortgateDetail)。我在迭代中执行此操作,因此每次迭代(每次调用)都会得到一行并将其添加到我的List colleciton中,然后一旦完成迭代,我将返回List。

无论出于何种原因,它似乎不想从返回的结果中获取单行并将其添加到我的列表中。我不知道我在这里做错了什么......我显然尝试了很多不同的变化......其中我的代码只返回结果中的一行,如下所示:

    public IHttpActionResult GetMultipleMorgagetDetail(ODataActionParameters parameters)
    {
        // Set up the parameters for the stored procedure
        SqlParameter[] sqlparams;
        sqlparams = new SqlParameter[2];

        sqlparams[0] = new SqlParameter("@Name", System.Data.SqlDbType.Char, 10);
        sqlparams[0].Value = parameters["Name"].ToString();

        sqlparams[1] = new SqlParameter("@Address", System.Data.SqlDbType.VarChar, 100);

        var addresses = parameters["Addresses"] as IEnumerable<string>;
        foreach (string name in addresses)
        {
            sqlparams[1].Value = name;
            var result = this.context.Database.SqlQuery<Entities.MortgateDetail>("dbo.sp_GetMortgageDetail @Name, @Address", sqlparams);

            return Ok(result.FirstOrDefault());
        }

        return Ok();
    }

而且,它运作正常。好吧,显然不是我想做的事情(而且我认为代码也没有多大意义),但是它并没有抛出任何运行时错误。所以,就好像“result.FirstOrDefault()”会在其他任何地方给我一个错误,但是当它用于从方法中返回一个值时...

谁能看到我做错了什么?

提前谢谢!

==========================================

更新

这是reqlly werid ...经过一番调查后,我发现当它试图不止一次调用“Database.SqlQuery()”时会抛出错误。

所以,只要我只调用sp一次,那么一切都没问题。然而,第二次我试图打电话给sp,它疯狂地说:(

以下代码将引发错误。在SQL事件探查器上,我只会看到一个sp调用:

    public IHttpActionResult GetMorgagetDetail(ODataActionParameters parameters)
    {
        // Set up the parameters for the stored procedure
        SqlParameter[] sqlparams;
        sqlparams = new SqlParameter[2];

        sqlparams[0] = new SqlParameter("@Name", System.Data.SqlDbType.Char, 10);
        sqlparams[0].Value = parameters["Name"].ToString();

        sqlparams[1] = new SqlParameter("@Address", System.Data.SqlDbType.VarChar, 100);
        sqlparams[1].Value = parameters["Address"].ToString();

        // Call the stored procedure twice
        var result = this.context.Database.SqlQuery<Entities.MortgateDetail>("dbo.sp_GetMortgageDetail @Name, @Address", sqlparams);
        result = this.context.Database.SqlQuery<Entities.MortgateDetail>("dbo.sp_GetMortgageDetail @Name, @Address", sqlparams);

        return Ok(result);
    }

我认为当我调用sp时,sp实际上并没有被调用,但是框架会对sp调用进行某种排队,并在它认为是执行它的最佳时间时调用它,并且它正在这样做拧紧一些东西,结果我不能连续两次(或多次)连续调用同一个sp ....

我知道这些都没有多大意义,但我真的没有看到我的代码中的逻辑缺陷。我不打算分享我在调查过程中尝试过的所有代码的不同变体,但有一次我对所有内容进行了硬编码,并使我的例行程序只是将sp调用回来,然后将其删除。

我有一个有趣的观察,当调用sp两次时,如果我用来分隔结果的变量(比如result1和result2),并且只返回一个变量(“return Ok(result1);”或“返回Ok(result2);“)然后不会抛出任何错误。但是,在Profiler上,我只能看到一个sp调用,这是我的函数返回的结果。

换句话说,即使我有一行调用sp并将返回的结果分配给我的代码中的变量,实际上也没有执行(一直到实际调用sp),除非我的代码实际上使用结果(即返回它)。这就是为什么我怀疑框架会进行某种流量控制并决定何时在后端使用sp ...这显然有一些bug。

我试图找出是否有办法强制框架提交数据库事务(= sp调用),或者清除结果,以便第二次调用相同的sp就像第一次调用它一样,我找不到任何东西。

Argggggg

0 个答案:

没有答案