图集中的Breeze + Knockout绑定

时间:2013-05-08 21:07:23

标签: knockout.js breeze

我在使用Knockoutjs绑定在Breezejs中保存现有数据图表的更新时遇到了问题。

我从John Papa的SPA开始使用HotTowel&迪朗达尔。

症状是,如果更新是医生的简单属性,我可以保存对医生记录的更新。但是,如果我在医生中包含的其中一个集合中添加一个新元素,我可以保存集合元素,但它会到达服务器并保存到数据库但是具有null属性并且没有引用医生。我正在使用Specialty作为示例,但我在医生记录中看到了与我添加项目的任何集合相同的行为。添加的项目将在所有属性中以空值出现在服务器上。

医生图表在页面上显示正常,我可以将下拉菜单与适当的特定字段的相应值相关联。复选框等也显示适当的值。

以下是我正在使用的HTML片段:

<div id="physGraph" class="span10" data-bind="with: currentPhysician()[0]">
    <!-- more stuff here -->
    <div id="physSpecialties" class="span8">
      <span class="span8">Physician Specialties<i class="icon-plus-sign" title="Add new specialty to physician" data-bind="click: $parents[0].addSpecialtyToPhysician"></i></span>
      <div class="span8 table-bordered" data-bind="foreach: physicianSpecialties">
        <div class="span8">
          <span data-bind="text: specialty().name()"></span>
        </div>
        <div class="span7  table-bordered">
          <i class="icon-remove-sign" title="Remove specialty from physician list" data-bind="click: $parents[1].removeSpecialtyFromPhysician"></i>
          <select data-bind="options: $parents[1].specialties(), optionsText: 'name', value: specialty()"></select>
        </div>
      </div>
    </div>
    <!-- more stuff here -->
 </div> <!-- end with: currentPhysician()[0]

以下是我如何找医生:

define([services/datacontext', 'viewmodels/physList'], function (datacontext, physListVm) {
  var initialized = false;
  var physNotes = ko.observableArray();
  var currentPhysician = ko.observable();
  var vm = {
    activate: activate,
    title: 'Physician Edit',
    currentPhysician: currentPhysician,
    addSpecialtyToPhysician: addSpecialtyToPhysician,
    save: save,
    // more code in here
  }

  // internal functions for physDetailEdit
   function activate() {
    initLookups();
    var physIdSelectedFromList = physListVm.selectedPhys().id();
    return getPhysicianDetail(physIdSelectedFromList);
  }

  function getPhysicianDetail(requestedPhysId) {
    var promise = datacontext.getPhysicianDetails(requestedPhysId, currentPhysician);
    return promise;
  }
  more code in here
}

以下是我添加专业的方法:

  function addSpecialtyToPhysician(item, event) {
    var newItem = datacontext.createSpecialty();
    item.physicianSpecialties.push(newItem);
    // I've also tried it like this -- > currentPhysician()[0].physicianSpecialties.push(newItem);
  }

以下是我保存记录的方式:

  function save() {
    return datacontext.saveChanges();
  }

以下是这两个项目的codeFirst描述:

  public class Physician
  {
    public Physician()
    {
      PhysicianSpecialties = new List<PhysicianSpecialty>();
      PhysicianPayers = new List<PhysicianPayer>();
      IncentivePrograms = new List<PhysicianIncentiveDetail>();
      PhysicianNotes = new List<Note>();
      PhysInOrgs = new List<PhysInOrg>();
      Memberships = new List<Membership>();
    }
    public Int32 Id { get; set; }
    public Person ContactInfo { get; set; }
    public ICollection<Membership> Memberships { get; set; }
    public ICollection<PhysicianIncentiveDetail> IncentivePrograms { get; set; }
    public ICollection<PhysicianPayer> PhysicianPayers { get; set; }
    public ICollection<PhysicianSpecialty> PhysicianSpecialties { get; set; }
    public ICollection<Note> PhysicianNotes { get; set; }
    public ICollection<PhysInOrg> PhysInOrgs { get; set; }
    public string Dea { get; set; }
    public string Npi { get; set; }
    public string Tin { get; set; }
    public string Ssn { get; set; }
    public string TaxId { get; set; }
    public string MedLicenseNbr { get; set; }
    public string MedLicenseState { get; set; }
    public DateTime? MedLicenseRecertDate { get; set; }
    public EMRSystem EmrSystem { get; set; }
    public int ImportBatchId { get; set; }
    public bool IsPcp { get; set; }
    public bool SoloPractitioner { get; set; }
    public bool PartOfHospital { get; set; }
  }

  public class PhysicianSpecialty
  {
    public Int32 Id { get; set; }
    public Physician Physician { get; set; }
    public Specialty Specialty { get; set; }
    public bool IsPrimary { get; set; }
  }

我保存的内容是:

Id  IsPrimary   Physician_Id    Specialty_Id
21  0           NULL            NULL

我假设通过向医师图表添加专业,当我将专业推到当前的医生()[0]时,Breeze会自动从页面上显示的下拉菜单中插入医生ID和所选专业。

有人能看到我错过的东西吗?

由于

2 个答案:

答案 0 :(得分:0)

看起来您的数据部分保存,因此不确定这是否与您的问题有任何关系,但我遇到了热毛巾模板和微风的问题。由于某种原因,即使通过nuget更新后,模板中的微风源也非常不同。尝试从breejejs下载并替换源。如果它不起作用你就不会变得更糟。我之前发布了我的问题

Errors when using Breeze with EF

答案 1 :(得分:0)

这个答案来自Ward Bell。不用说,它有效,我得救了!

问题被简化为医生记录中的单一收集:专业。我已将解决方案扩展到所有其他系列。

EF模型

您的PhysicianSpecialty.cs类定义如下:

public class PhysicianSpecialty
{
  public Int32 Id { get; set; }
  public Physician Physician { get; set; }
  public Specialty Specialty { get; set; }
  public bool IsPrimary { get; set; }
}

您缺少支持关联,外科医生和专业的外键(FK)。当您希望Breeze为您自动维护关联时,它需要FK。

此外,如果没有描述FK的元数据,Breeze.NET不知道如何设置EF生成的Physician_Id和Specialty_Id列。

我使用公共和显式外键重新定义了它

public class PhysicianSpecialty
{
  public Int32 Id { get; set; }
  public Int32 PhysicianId { get; set; }
  public Int32 SpecialtyId { get; set; }
  public Physician Physician { get; set; }
  public Specialty Specialty { get; set; }
  public bool IsPrimary { get; set; }
}

当EF重建表时,它现在有PhysicianId和SpecialtyId列。我选择这些名称是因为我喜欢它们比带有下划线的名字更好,并且它们恰好符合EF的惯例(强调的名字也可能是这样;我不记得了。)

现在,当您在BreezeJS客户端中分配关联并且所有内容都流向服务器时,将设置这些FK属性。

除了你还有其他两个问题。 Combobox KO绑定

details.js中的以下原始HTML行具有不正确的KO绑定:

  <select data-bind="options: $parent.specialties(), optionsText: 'name', value: specialty()"></select>

你想要的是这个:

  <select data-bind="options: $parent.specialties, optionsText: 'name', value: specialty" />

关键区别在于价值约束;你不能在专业之后拥有这些括号。

我无法解释原因。我的淘汰赛还不够好。在这种情况下,我真的很惊讶,因为我不认为额外的痛苦会受到伤害。显然他们这样做。顺便说一句,你绝对必须在路径中有中间值的parens,如

  data-bind="foreach: phys().physicianSpecialties"