0

.NET 4.5 の async/await 機能に頭を悩ませています。以下のコードを Web API コントローラーで使用して、フォームから複数のファイルを他のフォーム データと共にキャッチしています。フォームやデータの送信方法を制御することはできません。

私がやりたいことは、ファイルを受け取り、フォームからデータを取得し、そのフォーム データに基づいてデータベースを読み取り、ファイルを移動し、別のデータベース テーブルを更新することです。以下のコードを使用すると、ファイルまたはフォーム データを問題なく取得できます。フォーム データで渡された formID に基づいて、データベースからデータを取得します。

問題が発生したのは、データベースに書き戻すためにコードの下部にあるコメントを外したときです。3 つのファイルがあった場合、catch ブロックが例外をキャッチする前に、そのうちの 1 つだけが移動されます。私の問題は、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提供します。したがって、ほとんどの場合、コードについて通常の考え方で考えることができます。

問題が発生したのは、データベースに書き戻すためにコードの下部にあるコメントを外したときです。3 つのファイルがあった場合、catch ブロックが例外をキャッチする前に、そのうちの 1 つだけが移動されます。

これが私がこれから得たものです:

  • データベース コードが例外をスローしています。
  • 例外がスローされると、foreachループを離れてcatchハンドラーに移動します。

予想外のことは何もありません...

于 2013-04-16T14:52:40.303 に答える