2016-04-03 117 views
1

假設我想在此示例中保存訂單到數據庫PizzaOrderDialog.cs如何注入DbContext(或任何其他對象)到對話框?

我可以將DbConext注入控制器,這一個https://github.com/Microsoft/BotBuilder/blob/master/CSharp/Samples/PizzaBot/Controllers/MessagesController.cs但如何使用它在PizzaOrderDialog.cs

我不能只是通過的DbContext作爲構造參數PizzaOrderDialog類,因爲PizzaOrderDialog對象將被序列化和反序列化,然後。

這樣做的最佳方法是什麼?提前致謝!


MessageController.cs

[BotAuthentication] 
public class MessagesController : ApiController 
{ 
    private static IForm<PizzaOrder> BuildForm() 
    { 
     var builder = new FormBuilder<PizzaOrder>(); 

     ConditionalDelegate<PizzaOrder> isBYO = (pizza) => pizza.Kind == PizzaOptions.BYOPizza; 
     ConditionalDelegate<PizzaOrder> isSignature = (pizza) => pizza.Kind == PizzaOptions.SignaturePizza; 
     ConditionalDelegate<PizzaOrder> isGourmet = (pizza) => pizza.Kind == PizzaOptions.GourmetDelitePizza; 
     ConditionalDelegate<PizzaOrder> isStuffed = (pizza) => pizza.Kind == PizzaOptions.StuffedPizza; 

     return builder 
      // .Field(nameof(PizzaOrder.Choice)) 
      .Field(nameof(PizzaOrder.Size)) 
      .Field(nameof(PizzaOrder.Kind)) 
      .Field("BYO.Crust", isBYO) 
      .Field("BYO.Sauce", isBYO) 
      .Field("BYO.Toppings", isBYO) 
      .Field(nameof(PizzaOrder.GourmetDelite), isGourmet) 
      .Field(nameof(PizzaOrder.Signature), isSignature) 
      .Field(nameof(PizzaOrder.Stuffed), isStuffed) 
      .AddRemainingFields() 
      .Confirm("Would you like a {Size}, {BYO.Crust} crust, {BYO.Sauce}, {BYO.Toppings} pizza?", isBYO) 
      .Confirm("Would you like a {Size}, {&Signature} {Signature} pizza?", isSignature, dependencies: new string[] { "Size", "Kind", "Signature" }) 
      .Confirm("Would you like a {Size}, {&GourmetDelite} {GourmetDelite} pizza?", isGourmet) 
      .Confirm("Would you like a {Size}, {&Stuffed} {Stuffed} pizza?", isStuffed) 
      .Build() 
      ; 
    } 

    internal static IDialog MakeRoot() 
    { 
     return new PizzaOrderDialog(BuildForm); 
    } 

    public async Task<Message> Post([FromBody]Message message) 
    { 
     return await Conversation.SendAsync(message, MakeRoot); 
    } 
} 

PizzaOrderDialog.cs

[LuisModel("4311ccf1-5ed1-44fe-9f10-a6adbad05c14", "6d0966209c6e4f6b835ce34492f3e6d9")] 
[Serializable] 
public class PizzaOrderDialog : LuisDialog 
{ 
    private readonly BuildForm<PizzaOrder> MakePizzaForm; 

    internal PizzaOrderDialog(BuildForm<PizzaOrder> makePizzaForm) 
    { 
     this.MakePizzaForm = makePizzaForm; 
    } 

    [LuisIntent("")] 
    public async Task None(IDialogContext context, LuisResult result) 
    { 
     await context.PostAsync("I'm sorry. I didn't understand you."); 
     context.Wait(MessageReceived); 
    } 

    [LuisIntent("OrderPizza")] 
    [LuisIntent("UseCoupon")] 
    public async Task ProcessPizzaForm(IDialogContext context, LuisResult result) 
    { 
     var entities = new List<EntityRecommendation>(result.Entities); 
     if (!entities.Any((entity) => entity.Type == "Kind")) 
     { 
      // Infer kind 
      foreach (var entity in result.Entities) 
      { 
       string kind = null; 
       switch (entity.Type) 
       { 
        case "Signature": kind = "Signature"; break; 
        case "GourmetDelite": kind = "Gourmet delite"; break; 
        case "Stuffed": kind = "stuffed"; break; 
        default: 
         if (entity.Type.StartsWith("BYO")) kind = "byo"; 
         break; 
       } 
       if (kind != null) 
       { 
        entities.Add(new EntityRecommendation("Kind") { Entity = kind }); 
        break; 
       } 
      } 
     } 

     var pizzaForm = new FormDialog<PizzaOrder>(new PizzaOrder(), this.MakePizzaForm, FormOptions.PromptInStart, entities); 
     context.Call<PizzaOrder>(pizzaForm, PizzaFormComplete); 
    } 

    private async Task PizzaFormComplete(IDialogContext context, IAwaitable<PizzaOrder> result) 
    { 
     PizzaOrder order = null; 
     try 
     { 
      order = await result; 
     } 
     catch (OperationCanceledException) 
     { 
      await context.PostAsync("You canceled the form!"); 
      return; 
     } 

     if (order != null) 
     { 
      await context.PostAsync("Your Pizza Order: " + order.ToString()); 
     } 
     else 
     { 
      await context.PostAsync("Form returned empty response!"); 
     } 

     context.Wait(MessageReceived); 
    } 

    enum Days { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday }; 

    [LuisIntent("StoreHours")] 
    public async Task ProcessStoreHours(IDialogContext context, LuisResult result) 
    { 
     var days = (IEnumerable<Days>)Enum.GetValues(typeof(Days)); 

     PromptDialog.Choice(context, StoreHoursResult, days, "Which day of the week?"); 
    } 

    private async Task StoreHoursResult(IDialogContext context, IAwaitable<Days> day) 
    { 
     var hours = string.Empty; 
     switch (await day) 
     { 
      case Days.Saturday: 
      case Days.Sunday: 
       hours = "5pm to 11pm"; 
       break; 
      default: 
       hours = "11am to 10pm"; 
       break; 
     } 

     var text = $"Store hours are {hours}"; 
     await context.PostAsync(text); 

     context.Wait(MessageReceived); 
    } 
} 

回答

0

什麼你的要求做違反了MVC模式。

那就是 - 你不應該做一些控制型功能&直接在您的演示文稿(視圖)的代碼層又名PizzaOrderDialog.cs

與數據庫交互模型應該注入一個單參考您db_context到您的控制器(你已經有了部分)

在你的控制器中添加函數封裝這些db_context interactio ns作爲對話框,然後將這些函數的結果注入到對話框構造函數中,就像現在使用BuildForm<PizzaOrder> makePizzaForm一樣。

即使有說法,基於用戶在對話框中選擇的5x4x10建議的映射 - 將所有內容以序列化方式傳遞(如您所述),並讓您的服務器端視圖邏輯在PizzaOrderDialog.cs中工作所有可能性視圖模型比試圖公開模型層訪問要好。

對訂貨提交具體而言,我會一個靜態方法添加到您可以從再次封裝任何互動都需要與db_context做到這一點的對話框中調用該控制器。

+2

如果它是一個簡單的應用程序,那麼它可能是好的,但如果它是有可能獲得更多的複雜,我建議即使不注入db_context到控制器中的一切,而不是抽象出來到的一些其他層你的申請。 – mattherman