Linq to SQL クラスの継承と linq クエリの結果のキャスト
-
20-08-2019 - |
質問
私は、基本的なエンティティをさまざまなもの (従業員、車両など) に拡張する必要があるアプリケーションを作成しています。この設計では、エンティティ テーブルと、タイプ固有の値を含む 2 番目のテーブルが存在します。たとえば、従業員には ID 番号がありますが、車両には登録番号があります。
データ コンテキストで生成されたクラス エンティティから継承しましたが、リポジトリでのキャストで問題が発生しました。これを行う正しい方法は何ですか?
public class cAccountEmployee : cAccountEntity
{
public string id_number
{
get
{
try
{
return this.cAccountEntityValues.Single(e => e.type == 1).value;
}
catch (Exception)
{
return "";
}
}
set
{
try
{
this.cAccountEntityValues.Single(e => e.type == 1).value = value;
}
catch (Exception)
{
this.cAccountEntityValues.Add(new cAccountEntityValue()
{
accountentity_id = this.id,
cAccountEntity = this,
type = 1,
value = value
});
}
}
}
}
次に、私のリポジトリ内で(何も継承しません)
public IEnumerable<cAccountEmployee> All(int accountholder_id)
{
return db.cAccountEntities.Where(e => e.accountholder_id == accountholder_id).OrderBy(a => a.name).Cast<cAccountEmployee>();
}
public cAccountEmployee Single(int id)
{
return db.cAccountEntities.Single(a => a.id == id) as cAccountEmployee;
}
単一のメソッドでキャストが失敗するため、null が返されます。基本クラスとの間で明示的または暗黙的な演算子を定義することはできないと理解していますか?変更を送信できるようにデータベースの状態を維持しながら、基本クラスの Linq 結果を継承した Employee クラスにキャストするにはどうすればよいですか?
解決
LINQ-to-SQL では、継承が機能する方法が 2 つあります。
- 単一テーブルの識別子 (データが均一ではないため、適切ではありません)
- 基本クラス / マルチテーブル (これが DBML でサポートされていないわけではありません - クラスを手動で作成した場合のみ)
LINQ-to-SQL は複数テーブルの継承をサポートしていません (つまり、複数のテーブルのデータを含む単一のオブジェクト)。Entity Framework も同様ですが、より複雑です。あなたが使う .Cast<T>
そして .OfType<T>
EF では、サブタイプに基づいてキャスト/フィルター処理します。
以下をご覧ください。
- IDに基づいたクエリ (と組み合わせる
GetTable<T>()
) - dbml での基本クラスの指定
ここでの基本クラスの目的は何ですか?動作を追加する場合は、dbml を編集して、すべてのエンティティに共通の基本クラスを指定できます。ある場合 データのプロパティ その後はさらに厄介になります。
個人的には、この方法は絶対にしません...私は、タイプごとに別のクラスを保持し、タイプごとに別のテーブルを使用してデータコンテキストを正しく使用します。
public IEnumerable<Employee> All(int accountholder_id)
{
return db.Employees.Where(e => e.accountholder_id == accountholder_id)
.OrderBy(a => a.name);
}
public Employee Single(int id)
{
return db.Employees.Single(a => a.id == id);
}
それで、それが何であるかを明確にしてもらえますか cAccountEntity
ここにいますか?
他のヒント
の入力のためのおかげで、提案の一部をオーバーになります...
アカウントエンティティの背後にある考え方は、今のようサイトは従業員だけを処理する必要がありますが、将来的には、彼らはシステムになどの車両を追加することも、システムはエンティティへのコストを割り当てるために使用されていることだったので、この目的のために従業員は、車両と同様に扱われます。
従業員と彼の車の必要性は、DBなどで参照するために同じように扱いますが、それらについて少し異なる情報が必要になるということでアイデア。それは彼らが後に余分なタイプを追加したいという理由だけで、複雑な設計をされますが、DBをアップグレードするために必要とせず...
私のコードでは、しかし、私は、従業員ではない程度の一般的なエンティティタイプ(MVCアプリではるかに簡単等の閲覧、コントローラを作る)についてお話したいと思います。あなたは派生クラスに基本からユーザー定義のキャストを供給することができないとして、私はそれをinherittingスキップされ、代わりに以下のソリューションを使用しています。もう少し面倒なく、仕事...誰かがこれを行うのより良い方法を見ることができるなら、私に教えてくださいん。
public class cAccountEmployee
{
private cAccountEntity entity;
public int id
{
get
{
return this.entity.id;
}
set
{
this.entity.id = value;
}
}
public string name
{
get
{
return this.entity.name;
}
set
{
this.entity.name = value;
}
}
public int accountholder_id
{
get
{
return this.entity.accountholder_id;
}
set
{
this.entity.accountholder_id = value;
}
}
public System.Data.Linq.EntitySet<cAccountEntityValue> cAccountEntityValues
{
get
{
return this.entity.cAccountEntityValues;
}
}
public cAccountHolder cAccountHolder
{
get
{
return this.entity.cAccountHolder;
}
}
public cAccountEmployee()
{
this.entity = new cAccountEntity();
}
public cAccountEmployee(cAccountEntity entity)
{
this.entity = entity;
}
public string id_number
{
get
{
try
{
return this.entity.cAccountEntityValues.Single(e => e.type == 1).value;
}
catch (Exception)
{
return "";
}
}
set
{
try
{
this.entity.cAccountEntityValues.Single(e => e.type == 1).value = value;
}
catch (Exception)
{
this.entity.cAccountEntityValues.Add(new cAccountEntityValue()
{
accountentity_id = this.id,
cAccountEntity = this.entity,
type = 1,
value = value
});
}
}
}
}
//In the repository
public cAccountEmployee Single(int id)
{
return new cAccountEmployee(db.cAccountEntities.Single(a => a.id == id));
}
どのように継承されたEmployeeクラスまでキャストするために、基本クラスのLINQの結果を得ることができます。
それは意気消沈だ、アップキャストはありません。
私は、あなたがキャスティングまたは多分理解していないと思います - 。参照型対インスタンスタイプを
public class Animal { }
public class Zebra : Animal { }
public class Zoo
{
public void ShowZebraCast()
{
Animal a = new Animal();
Zebra z = (Zebra)a;
}
}
System.InvalidCastExceptionの:「ゼブラ」を入力するタイプのオブジェクトをキャストできません「動物」
。と同じように、あなたは意気消沈していないことに対して従業員の参照を使用することができますエンティティのインスタンスを持っています。
あなたは型を変換することもできますが、あなたは変換方法を提供する必要があります。
public partial class Animal { }
public class Zebra : Animal { }
//in another file
public partial class Animal{
public Zebra ToZebra(){
return new Zebra() { //set Zebra properties here.
};
}
}
public class Zoo
{
public void ShowZebraConvert()
{
Animal a = new Animal();
Zebra z = a.ToZebra();
}
}