この質問は関連しています `Employee`クラスはどのように設計する必要がありますか?
上記の質問では、従業員を一意に識別するために、各Employee
オブジェクトには、次に示すようにid
フィールドがあります
class Employee
{
private int id // id is given by the database
// Employee data (let's say, dozens of properties).
//methods.....
}
従業員オブジェクトのid
は、データベースによって提供されます。
したがって、新しい従業員を説明するためにオブジェクトを使用する場合、まだ保存するid
はありません。ただし、既存の従業員を表すオブジェクトにはid
があります。だから私は時々オブジェクトを説明し、時々説明しないプロパティを持っています。
また、id = null
はEmployee
オブジェクトの状態を無効にしますが、
[A]適切にカプセル化されたオブジェクトは、パブリックインターフェイスを介して無効な状態にすることはできません[...]
https://softwareengineering.stackexchange.com/a/258281/234665
最初のid = null
が原因で、この設計はカプセル化に違反していますか?
最も簡単な方法は、知覚された問題を単に無視することです。データベース内のアイテムには、データベースによって提供されるIDがあります。データベースにないアイテムにはIDがありません。どちらも有効な状態です。 「挿入」は、アイテムにnullではないIが含まれている場合、有効な操作ではありません。また、アイテムがデータベースにない場合、「更新」は無効な操作です。
Idを不変にするかどうかを決定できます。この場合、データベースにアイテムを追加すると、idが変更された新しいアイテムが作成されます。
真実の単一の情報源を特定します。それが権威です。
あなたのプログラムが、従業員で起こりうることと起こり得ないことに対する権限である場合、DBは従業員情報を永続化する方法に他なりません。 DB IDは重要ではありません。オブジェクトモデルには、エンティティを識別および関連付ける独自の方法があります。
DBが、従業員で起こり得ることと起こり得ないことに対する権限である場合、IDのない従業員オブジェクトは、単に従業員を作成するための保留中の要求です。 IDを持つ従業員オブジェクトは、従業員の状態の古いレポートです。従業員オブジェクトが、従業員の状態に関する唯一の真実の情報源になることは決してありません。変更したいものはすべて、DBに対してチェックする必要があります。
したがって、新しい従業員を説明するためにオブジェクトを使用する場合、まだ保存する
id
はありません
そして、彼らは従業員ではありません。彼らは申請者です。したがって、Employee
タイプを使用しないでください。このシナリオの表現方法に苦労しているのは、間違ったタイプを使用しているためです。
1つの方法は、データベースに保存される前に、新しいエンティティが有効な識別子を持っていることを確認することです。これはまさにUUIDタイプの利点です。新しい識別子を取得するためにデータベースをクエリする必要はありません。代わりに、新しいUUIDを作成し、knowが一意であること、つまり、データベースに同じ識別子を持つ他のエンティティがないことを確認します。
別の方法は、まだ作成していない場合にEmployee
クラスのインスタンスを作成しないようにすることです。つまり、アプリケーションのユーザーが従業員を作成する場合、最初のステップは、データベース内の行をINSERT
ingし、有効な識別子(および、存在する場合はその他のデフォルト値)を取得することです。その後、(データベースから取得した情報から)Employee
クラスのインスタンスを初期化します。
この2番目のアプローチには、当然のことながら1つの欠点があります。ユーザーがフォームを作成したくないとしても、ユーザーがフォームを開いて不注意で作成した多くの未使用のエンティティが生じる可能性があります。この問題を軽減する1つの方法は、ユーザーがボタンをクリックしたり、ページを開いたりした場合にエンティティが作成されるという事実について、ユーザーインターフェイスが明確であることを確認することです。既に作成されたエンティティのリストを表示すると、すぐにフィードバック。別のアプローチは、ユーザーがエンティティーに何も保存していない場合、エンティティーを空としてマークすることです。空のエンティティは、毎晩など定期的に削除できます。
最後に、3番目の方法は、識別子のない従業員を表す基本クラスを持つことです。ただし、これによりコードが必要以上に複雑になるため、このアプローチは、明らかにメリットがある場合にのみ使用してください。
タイトルの質問に対する答えが何であるかわかりません。
しかし、現実には、現実のシナリオに適用すると、すべての理論的アイデアが壊れてしまいます。したがって、ソフトウェア設計は妥協の仕事です。 「オブジェクトは常に正しい状態である」という理想的なシナリオを破って、データベースに挿入される前にIDなしで従業員が存在できるようにしますか?または、従業員に作成時のIDを提供できるシステムを作成しますか?オプションはたくさんあります。 GUIDを使用します。または、空の行を事前に挿入してIDを取得します。または Hi\Loアルゴリズム を使用します。
結局のところ、どのオプションが最適かは、あなた、あなたの(できれば広範囲にわたる)経験、および特定の要件次第です。
適切にカプセル化されたオブジェクトは、パブリックインターフェイスを介して無効な状態にすることはできません...
そこで言及されているように、適切にカプセル化することが重要です。 Id
のカプセル化はどこにありますか?カプセル化しないと、_private int Id
_の内容がわかりません。
次のようにカプセル化できます。
_class Employee
{
private int Id;
public int ID
{
get => Id;
set
{
if (value > 0)
{
Id = value;
}
}
}
// other properties and methods.
}
_
このEmployee
クラスの何が問題になっていて、Id
が無効になっているのですか?このId
は、コードを適切に設計せず、有効な値がないときにCRUD操作を実行しようとすると無効になる場合があります。
これを実現するには、Id
をチェックして、実行するメソッドを決定できます。 0の場合は挿入します。そうでない場合は、更新してください。 Entity Framework AddorUpdate(TEntity model)
拡張メソッドは、この良い例です。