[英]Complex (Multi-Schema) Entity Framework object mapping for seamless integration (and eventual replacement) of an office management application
我是一个相当新手,是程序员。 这是我的第一个问题,但是几个月来我一直在使用stackoverflow获取有价值的信息。
我目前在一个很小的(少于10名员工)专科医生办公室工作,几乎是千篇一律的工作,这使我处于一个独特的位置,在这里我可以自由支配(并获得适度的资源支持)来开发和实施任何类型的应用程序/当前系统运行良好,因此没有任何需求或压力的工具。
目前,我们运行的是一个过时的(大约2008年)医疗办公室管理系统,该系统负责处理患者的商业帐户,账单和保险索赔。 办公室本身是相当危险的网络。 我们有几台使用标准DICOM的诊断机,但大多数病历仍然是纸质的。
我的期望可能超出了我目前的期望,但我计划逐步开发一个功能更广泛,领域驱动的应用程序,将电子病历(评估/管理和DICOM诊断)与医疗办公室管理相结合结束。 一旦有了这样一个应用程序的框架,我所处的沙箱环境就会吸引我,我可以探索和开发任何我梦dream以求的自动化或工具。
我在这类事情上的经验非常有限,但是我是一个非常有决心的人,我喜欢应用程序驱动的学习。
我正在首先与当前的患者账户数据库进行集成。
当前所有内容都存储在FoxPro 2.5免费表中。 表之间的关系不是隐式可获得的,但是隐含了很多关系。 理想情况下,我希望将带有POCO的新应用程序通过EF映射到SQL数据库。 该部分很简单,但是我也想在单独的DBContext中将相同的POCO映射到当前的FoxPro 2.5 .dbfs(不一定具有相同的架构)。
我能想到这样的事情吗? 我一直在测试派生所有fluentAPI映射( .ToTable()
.HasColumnName()
等)的艰巨任务,但这是一项艰巨的任务,我希望在潜水之前先获得一些更有经验的见解。 我找不到任何相关示例,说明有人在尝试我的尝试,这也有些令人沮丧。
也许我的方法是错误的。 我愿意进行相应的调整,但是我喜欢在应用程序中使用POCO的想法,这对于我的新应用程序能够与旧数据库进行对话而不实现其非直观的模式非常重要。
令人头疼的主要目的是在保持当前应用程序正常运行的同时,还允许我运行和开发新应用程序。
是否可以使用EF将新的OOR /域驱动的应用程序与模式稍有不同的旧数据库集成在一起? 如果是这样,有什么提示或示例可以帮助我入门吗? 如果没有,我还有其他功能类似的替代品吗? 谢谢
从现在开始,我将当前使用的应用程序称为AppX。
App X的前身在Unix上运行,也位于FoxPro / xBASE表上,因此App X可能是在此之上构建的,以简化客户升级的过程。 App X目录还包含Visual Fox Pro 6 .dlls和带有FoxPro .ico且名称为“ fbaseeng”的应用程序文件,该文件将弹出标题为“ DTS Command Prompt”的命令提示符窗口。 我不确定App X的运行方式如何,但是'DTS'仍然困扰着我,我花了一些时间看是否有一种方法可以使用他们已经实现的任何数据转换,但是我最终放弃了。
当前数据库是231个 .dbf
表的集合。 幸运的是,它们中的很大一部分似乎完全没有被使用,或者仅以某种回旋的临时方式使用,它们不会在App X的运行时之外存储记录。
几个表似乎是链接表,其中的另一部分包含诸如类型限定符属性之类的参考数据
public partial class Accttype
{
public decimal Acct_Type { get; set; }
public string Acct_Desc { get; set; }
public string Sb { get; set; }
public decimal Fee { get; set; }
public bool Acptasgn { get; set; }
public decimal Insclass1 { get; set; }
public decimal Insclass2 { get; set; }
public decimal Insclass3 { get; set; }
public decimal Insclass4 { get; set; }
public decimal Insclass5 { get; set; }
public string Acct_Grp { get; set; }
}
和静态参考值(例如邮政编码)
public partial class Zip
{
public string Zipcode { get; set; }
public string City { get; set; }
public string St { get; set; }
public string Areacode { get; set; }
public decimal Ext_From { get; set; }
public decimal Ext_To { get; set; }
}
到目前为止,我最关注以下表格:
-Patdemo.dbf包含所有访问该诊所的患者的记录。 它有大约100列,包含大量信息,包括姓名,地址,保险类型,运行帐户余额总计等。简单明了的主键是患者ID,但格式为'0.0'。
-Billing.dbf包含在特定服务日期与患者相关联的字母数字ID索引的账单。 大约有80列,主要包括外键/类型限定符和状态指示符(即INS1_SENT
)。 拥有患者ID的FK
-Charges.dbf包含每个法案下的行项目。 它是每个继承的表,也可以是费用和过帐/付款的联接,因为它在“类型”列中包含C
或P
表示的两条记录。 似乎没有一个简单的主键,但是Charges
具有ChargeID
,而ChargeID
/ Payments具有PostID
,两者的格式BillID+"000N"
。 但是,要扔曲线球,排空调整没有ChargeID
/ PostID
。 拥有BillID
FK。
-Insur.dbf包含保险提供商和从地址到电子帐单ID的信息。 主键是字母数字ICode(例如:BC01)。
-Patins.dbf似乎是一个链接表,但还包含诸如该保单的患者保险ID号之类的信息。 具有患者ID和ICode
FK。
我还希望与其他各种参照表保持一致(例如诊断,推荐医生和CPT代码),但是它们现在的优先级较低。
我还没有完全设计新应用程序的架构,但是我知道它将更加合乎逻辑,因为诸如地址之类的东西将是一种具体的类型,而不管它是与患者还是与保险公司相关联。
为了这个示例,让我们看一下已经存在的Patins.dbf
POCO(这是最小的表之一):
public partial class Patins
{
public decimal Custid { get; set; }
public decimal Inskey { get; set; }
public string Insurcode { get; set; }
public string Insurnum { get; set; }
public string Groupnum { get; set; }
public string Guarlname { get; set; }
public string Guarfname { get; set; }
public string Guarmi { get; set; }
public string Guargen { get; set; }
public string Guaraddr { get; set; }
public string Guaraddr2 { get; set; }
public string Guarcity { get; set; }
public string Guarst { get; set; }
public string Guarzip { get; set; }
public string Guarcountr { get; set; }
public string Guarphone { get; set; }
public string Guaremail { get; set; }
public System.DateTime Guardob { get; set; }
public string Guarsex { get; set; }
public string Guaremp { get; set; }
public decimal Relation { get; set; }
public System.DateTime Startdate { get; set; }
public System.DateTime Enddate { get; set; }
public bool Active { get; set; }
public string Bcpc { get; set; }
public string Auth1 { get; set; }
public string Auth2 { get; set; }
public string Auth3 { get; set; }
public decimal Billcnt { get; set; }
public string Desc1 { get; set; }
public string Desc2 { get; set; }
public string Desc3 { get; set; }
public decimal Visits1 { get; set; }
public decimal Visits2 { get; set; }
public decimal Visits3 { get; set; }
public System.DateTime From1 { get; set; }
public System.DateTime From2 { get; set; }
public System.DateTime From3 { get; set; }
public System.DateTime To1 { get; set; }
public System.DateTime To2 { get; set; }
public System.DateTime To3 { get; set; }
public string Insnote { get; set; }
public string Char1 { get; set; }
public string Char2 { get; set; }
public string Char3 { get; set; }
public string Char4 { get; set; }
public string Char5 { get; set; }
public string Char6 { get; set; }
public string Char7 { get; set; }
public string Char8 { get; set; }
public string Char9 { get; set; }
public string Char10 { get; set; }
public System.DateTime Date1 { get; set; }
public System.DateTime Date2 { get; set; }
public decimal Num1 { get; set; }
public decimal Num2 { get; set; }
public string Createby { get; set; }
public System.DateTime Createdt { get; set; }
public string Modifyby { get; set; }
public System.DateTime Modifydt { get; set; }
public string Cobmemo { get; set; }
public System.DateTime Dinju { get; set; }
public System.DateTime Dsimbd { get; set; }
public System.DateTime Dsimed { get; set; }
public string Createtm { get; set; }
public string Modifytm { get; set; }
public bool Archive { get; set; }
public bool Delflag { get; set; }
public decimal Coinsded { get; set; }
public decimal Outpoc { get; set; }
public System.DateTime Lastupd { get; set; }
public decimal Coins { get; set; }
public decimal Msp { get; set; }
}
在现实世界中,患者通过保险单与保险公司建立联系。 有FK_PatientID
, FK_InsuranceCarrierID
和唯一ID PK_PolicyNumber
(为了安全起见,可能有PolicyNumber + InsuranceCarrierID?)。 保单具有规定付款的福利信息,配偶/家人可以共享保单(通常在保单号后附加-0n)。
我可能会让Patient
对象包含一组保险单对象。 遵循以下原则:
class Patient : Person
{
int PatientID { get; set; }
virtual IEnumerable<InsurancePolicy> InsurancePolicies { get; set; }
}
class InsurancePolicy
{
int PatientID { get; set; }
string PolicyNumber { get; set; }
string GroupNumber { get; set; }
bool IsActive { get; set; }
DateTime startDate { get; set; }
DateTime endDate { get; set; }
int InsuranceCarrierID { get; set; }
virtual Person Guarantor { get; set; } //all guarantor information accessible via person aggregate root i.e: Guarantor.FirstName
string GuarantorRelation { get; set; }
string[] Benefits { get; set; } //delineated set of benefit descriptions... automatically parse from EDI benefits message?... seperate value object class?... could contain copay/deduc/OoP
decimal Deductible { get; set; }
decimal Copay { get; set; }
decimal OutofPocket { get; set; }
virtual IEnumerable<Bill> AssociatedBills { get; set; } //all bills associated with policy... could also be InsuranceClaim objects... Automapper Bill->Claim?
}
在InsurancePolicy中或在其他地方还需要表示其他几项内容,例如工资率百分比,但我暂时不讨论它们。
在寻找将数据映射到旧FP表或从旧FP表映射数据时,我的问题终于到来了。 专门查看Guarantor
:作为Person
对象,它将存储在SQL模式的继承表中,那么进行映射的最佳方法是什么? 简单地.ToTable("Patins")
在InsurancePolicyMap
与(t => t.Guarantor.FirstName).HasColumnName("Guarfname")
似乎是合乎逻辑的,但并不EF自动采取单独的关系模式的照顾? 可能措辞更好:导航物理Person.FirstName
,SQLMap, InsurancePolicy.Guarantor.FirstName
,VFPmap和物理Patins.Guarfname
之间的关系/继承是否有困难?
那Billcnt
呢? 幸运的是,由于某种原因,它没有在App X中实现,但是对于我认为是AssociatedBills.Count()
的映射将是什么? 您是否只需从FP表中提取值来检查有效性?
由于您拥有“自由统治”的权利,因此我将借此机会升级整个系统。 这是一个非常非常差的数据模型,并且再长时间拖延此传统也没有用。 这些没有描述性的重复编号字段将持续引起混乱和错误。 从那里建立一个体面的领域几乎是不可能的。 实体框架具有与数据模型不同的塑造类模型的多种选择,但这太多了。 确实,在保留数据模型的同时重建应用程序是没有用的。
您绝对应该规范化数据模型。 创建表,例如Insclass
的外键到Accttype
等等。 还有一个FK到InsurancePolicy
的Benefit
表,因为您不能将字符串数组映射到数据库列。
但是首先(也是最重要的)要弄清楚需求。 完全自由地构建“任何类型的应用程序”听起来不错,但是用户始终牢记一些东西。 在您只键入一行代码之前,我将花足够的时间去动脑筋。 同意首先要做的事情。 然后在用例之后开始构建应用程序用例。 让他们测试每个用例。 这将使他们有时间习惯于新系统,并逐渐脱离旧系统,并在您进行操作时微调需求。 (简而言之,这是敏捷开发)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.