2016-04-03 104 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