2

私はかなり初心者で、熱狂的なプログラマーです。これは私の最初の質問ですが、貴重な情報を得るために数か月前からスタックオーバーフローを使用しています。

まず、いくつかのコンテキスト:

非常に小規模な (従業員が 10 人未満) 専門の医師の診療所での私の現在のやや何でも屋の仕事は、あらゆる種類のアプリケーションを開発および実装するための自由な統治 (および適度なリソースの支援) があるというユニークな立場に私を置きました/現在のシステムは十分に機能しているため、要求やプレッシャーは一切ありません。

私たちは現在、かなり古い (2008 年頃) の診療所管理システムを運用しており、患者のビジネス アカウント、請求、保険請求の提出を処理しています。オフィス自体はかなり偶然にネットワーク化されています。標準の DICOM を使用する診断機が 2 台ありますが、医療記録の大部分は紙のままです。

私は現在、自分の願望を噛み砕くことができる以上のことをしているかもしれませんが、電子医療記録 (評価/管理および DICOM 診断) を診療所管理と結び付ける、より包括的でドメイン駆動型のアプリケーションをゆっくりと開発する計画があります。終わり。そのようなアプリケーションのフレームワークが構築されると、自分の状況のサンドボックスの側面に惹きつけられ、夢見ることができるあらゆる種類の自動化やツールを探求して開発できるようになります。

正直に言うと:

私の経験はそのようなことで非常に限られていますが、私は非常に決心した個人であり、アプリケーション主導の学習が大好きです.

私の質問:

私は、現在の患者アカウントのデータベースとの最初の統合に取り組んでいます。

現在、すべてが FoxPro 2.5 の空きテーブルに格納されています。テーブル間の関係は暗黙的に取得できませんが、かなりの数が暗黙的に取得されます。理想的には、POCO を EF で SQL データベースにマップした新しいアプリケーションを作成したいと考えています。その部分は簡単ですが、別の DBContext で同じ POCO を現在の FoxPro 2.5 .dbfs (必ずしも同じスキーマを持つとは限りません) にマップしたいと思います。

私が想像しているようなことは可能ですか?私はすべての fluentAPI マッピング ( .ToTable().HasColumnName()など) を導出する水域をテストしてきましたが、それはかなり困難な作業であり、最初に飛び込む前に、より経験豊富な洞察が必要です。私が試みていることをやってのける誰かの関連する例を見つけることができませんでした。

おそらく私のアプローチは間違っています。それに応じて調整しても構わないと思っていますが、アプリケーションで POCO を使用するというアイデアが気に入っています。新しいアプリケーションが、直感的でないスキーマを実装せずに古いデータベースと通信できることが非常に重要です。

すべての頭痛の主な目的は、現在のアプリケーションを完全に機能させながら、同時に新しいアプリケーションを実行および開発できるようにすることです。

つまり、一言で言えば:

EF を使用して、新しい OOR/ドメイン駆動型アプリケーションをわずかに異なるスキーマの古いデータベースと統合することは可能ですか? もしそうなら、私を始めるためのヒントや例はありますか? そうでない場合、他の機能的に類似した代替手段はありますか? ありがとう


編集1:

現在使用しているアプリケーションを App X と呼びます。

App X の前身は Unix 上で動作し、FoxPro/xBASE テーブル上にも置かれていたため、App X はおそらく顧客のアップグレードを簡単にするために、その上に構築されました。App X ディレクトリには、Visual Fox Pro 6 .dll と、FoxPro .ico と「fbaseeng」という名前のアプリケーション ファイルも含まれており、「DTS コマンド プロンプト」というタイトルのコマンド プロンプト ウィンドウが表示されます。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 インデックス付き請求書が含まれています。主に外部キー/型修飾子とステータス インジケーター (つまりINS1_SENT) を含む約 80 の列があります。患者 ID の FK を持つ

- Charges.dbf 各 Bill に該当する項目が含まれます。これは、継承ごとのテーブル、または料金と転記/支払いの結合のいずれかであり、Cまたは P タイプ列で示される両方のレコードが含まれています。単純な主キーはないようですが、ChargesChargeIDPostings/Payments にはがありPostID、どちらも format がありますBillID+"000N"。ただし、変化球を投げるために、ボイド調整にはChargeID/がありませんPostID。の FK を持っていBillIDます。

- Insur.dbf 保険会社と住所から電子請求 ID までの情報が含まれています。主キーは英数字の ICode (例: BC01) です。

- Patins.dbf リンク テーブルのように見えますが、保険証券の患者の保険 ID 番号などの情報も含まれています。患者 ID と の FK がありICodeます。

並行性を維持したい参照テーブルは他にもさまざまあります (診断、紹介医師、CPT コードなど) が、現時点では優先順位が低くなります。

新しいアプリケーションのスキーマはまだ完全には設計していませんが、患者または保険会社に関連付けられているかどうかに関係なく、Addresses などのものが具象型になるという点で、はるかに論理的であることはわかっています。

この例のために、既存のPatins.dbfPOCO を見てみましょう (これは最小のテーブルの 1 つです)。

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_PatientIDFK_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 テーブルとの間でデータをマッピングする方法を探しているときに最終的に到着します。具体的にGuarantor: をPersonオブジェクトとして見ると、SQL スキーマの継承テーブルに格納されるため、マッピングを行う最善の方法は何ですか? 単純.ToTable("Patins")InsurancePolicyMapwith(t => t.Guarantor.FirstName).HasColumnName("Guarfname")は論理的に思えますが、EF は個別のリレーションシップ パターンを自動的に処理するのでしょうか? Person.FirstNameおそらくより良い表現: 物理、SQLMap、InsurancePolicy.Guarantor.FirstNameVFPmap、および物理の間にある関係/継承をナビゲートするのに問題がありPatins.Guarfnameますか?

どうBillcntですか?幸いなことに、何らかの理由でApp Xには実装されていませんが、私が想定しているもののマッピングはどうなるでしょうAssociatedBills.Count()か? FP テーブルから値を取得して有効性を確認しますか?

4

1 に答える 1

0

あなたには「自由な統治」があるので、システム全体をアップグレードする機会があります. これは非常に貧弱なデータ モデルであり、このレガシーをこれ以上引きずっても意味がありません。これらの何の変哲もない反復的な番号付きフィールドは、混乱とバグの継続的な原因となります。そして、そこからまともなドメインを構築することは事実上不可能です. Entity Framework には、データ モデルとは異なる方法でクラス モデルを形成するためのオプションがたくさんありますが、これでは多すぎます。実際、データ モデルを維持したままアプリケーションを再構築しても意味がありません。

データモデルは確実に正規化する必要があります。Insclass外部キーなどを使用してテーブルを作成しますAccttype。また、文字列配列をデータベース列にマップできないBenefitため、FK を持つテーブル。InsurancePolicy

しかし、最初に (そして何よりも) 要件を明確にします。「あらゆる種類のアプリケーション」を自由に構築できるというのは良いことですが、ユーザーは常に何かを念頭に置いています。コードを1行入力する前に、彼らの頭脳を選ぶのに十分な時間がかかります. 最初に行うことについて合意します。次に、ユースケースごとにアプリケーションのユースケースの構築を開始します。そして、それぞれのユース ケースをテストしてもらいます。これにより、新しいシステムに慣れ、古いシステムからゆっくりと切り離し、要件を微調整する時間が与えられます。(これは一言で言えばアジャイル開発です)。

于 2013-11-10T21:37:53.523 に答える