0

我无法理解 .NET 4.5 中的 async/await 功能。我在 Web API 控制器中使用下面的代码从表单中捕获多个文件以及其他一些表单数据。我无法控制表单或它如何发送数据。

我想要做的是接收文件,从表单中获取数据,基于该表单数据读取数据库,移动文件,并更新另一个数据库表。使用下面的代码,我可以轻松获取文件或表单数据。我根据表单数据中传递的 formID 从数据库中获取数据。

当我取消注释底部附近的代码以写回数据库时,我遇到了问题。如果我有三个文件,那么在 catch 块捕获异常之前,只有其中一个会被移动。我假设我的问题与 PostFile 方法是异步的事实有关。

编写此代码以使其正常工作的正确方法是什么?

public async Task<HttpResponseMessage> PostFile()
{
    // Check if the request contains multipart/form-data. 
    if (!Request.Content.IsMimeMultipartContent())
    {
        throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    }

    string root = GetRootPath();
    var provider = new MyMultipartFormDataStreamProvider(root);
    string logfile = root + "/form_data_output.txt";

    try
    {
        // Read the form data and return an async task. 
        await Request.Content.ReadAsMultipartAsync(provider);

        string form_id = provider.FormData.Get("FormId");

        string driver_id = GetDriverID(form_id);  // returns an int as a string

        string location = ConfigurationManager.AppSettings["storagePath"];
        location += form_id + "\\";

        //// make sure the new directory exists
        if (!Directory.Exists(location))
        {
            Directory.CreateDirectory(location);
        }

        var keys = provider.FormData.Keys.Cast<string>();
        foreach (var k in keys.Where(k => k.StartsWith("FormViewer") == true))
        {
            string filename = provider.FormData.Get(k) + ".pdf";
            string type_key = "FormType_" + k.Substring(k.IndexOf('_') + 1);
            string type_value = provider.FormData.Get(type_key);

            // setup the full path including filename
            string path = root + "\\" + filename;
            string newFullPath = location + filename;

            // move the file
            File.Move(path, newFullPath);
            if (File.Exists(newFullPath))
            {
                 if (File.Exists(newFullPath))
                {
                    try
                    {
                        string conn_str = ConfigurationManager.ConnectionStrings["eMaintenanceConnection"].ConnectionString;
                        using (SqlConnection conn = new SqlConnection(conn_str))
                        {
                            SqlCommand cmd = new SqlCommand("INSERT INTO eSubmittal_Document VALUES (null,@driver_id,@location,@doctype)");
                            cmd.Parameters.AddWithValue("@driver_id", driver_id);
                            cmd.Parameters.AddWithValue("@location", location);
                            cmd.Parameters.AddWithValue("@doc_type", type_value);
                            conn.Open();
                            int c = await cmd.ExecuteNonQueryAsync();
                            conn.Close();
                        }
                    }
                    catch (Exception e)
                    {
                        LogEntry(logfile, e.Message);
                    }
                }
            }
        }

        return Request.CreateResponse(HttpStatusCode.OK);
    }
    catch (System.Exception e)
    {
        return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
    }
}
4

2 回答 2

1

async并为异步代码await提供自然的程序流程。因此,在大多数情况下,您可以按照通常的方式思考代码:

当我取消注释底部附近的代码以写回数据库时,我遇到了问题。如果我有三个文件,那么在 catch 块捕获异常之前,只有其中一个会被移动。

这是我从中得到的:

  • 您的数据库代码正在引发异常。
  • 当异常被抛出时,它离开foreach循环去catch处理程序。

没有什么出乎意料的...

于 2013-04-16T14:52:40.303 回答
0

在不知道异常的情况下很难提供太多帮助,但是在异步方法中执行同步数据库操作对我来说似乎是个坏主意。尝试更改您的代码以使用:

int c = await cmd.ExecuteNonQueryAsync();
于 2013-04-16T14:51:05.597 回答