我在使用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和所选专业。
有人能看到我错过的东西吗?
由于
答案 0 :(得分:0)
看起来您的数据部分保存,因此不确定这是否与您的问题有任何关系,但我遇到了热毛巾模板和微风的问题。由于某种原因,即使通过nuget更新后,模板中的微风源也非常不同。尝试从breejejs下载并替换源。如果它不起作用你就不会变得更糟。我之前发布了我的问题
答案 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"