製品の製造エラーをキャプチャする 3 つのテーブルの 1 つをクエリする ASP.NET アプリケーションを構築しています。もちろん、各テーブルは EF エンティティに反映されます。どのテーブルが照会されるかは、ページが送信され、照会するエラーを示すフラグが設定されるまで決定されません。
3 つのエンティティにはそれぞれ、多くの共通点があります。これらの共通点は、インターフェイスで定義され、エンティティによって (部分的なクラス定義を介して) 実装されています。したがって、これらの部分クラスは次のようになります...
public partial class ProductException : IExceptionEntity { }
public partial class PartException : IExceptionEntity { }
public partial class RebuildException: IExceptionEntity { }
リポジトリ クラスで、指定した例外エンティティをクエリできるジェネリック メソッドを定義しました。メソッドにパラメーターとして渡される WHERE 句には、インターフェイスで定義されておらず、個々の例外エンティティ (製品、部品、および再構築) に固有のフィールドが含まれている可能性があるため、これは必須です。したがって、それらを呼び出すと、次のようになります..
IQueryable<ProductException> prodQuery = Repository.GetFilteredQuery<ProductException>(query, whereClause);
IQueryable<PartException> partQuery = Repository.GetFilteredQuery<PartException>(query, whereClause);
IQueryable<RebuildException> rebuildQuery = Repository.GetFilteredQuery<RebuildException>(query, whereClause);
ウェブページが複数のクエリを定義することは決してなく、クエリの結果に関係なく、クエリの結果で行うことはかなり似ているため、変数/プロパティを割り当てることができるようにしたいと思いますどのエンティティがクエリされたかに関係なく、クエリ/結果にアクセスするために使用します。以下のようなもの...
protected override void OnPreLoad(EventArgs e)
{
InitializeExceptionQuery();
}
List<IExceptionEntity> _exceptionList = null;
public List<IExceptionEntity> ExceptionList
{
get
{
if(_exceptionList == null)
_exceptionList = LookupQuery.ToList();
return _exceptionList;
}
}
IQueryable<IExceptionEntity> _query = null;
public IQueryable<IExceptionEntity> LookupQuery
{
get
{
if(_query == null)
_query = GetExceptionQuery(this.ExceptionCategory);
return _exceptionList;
}
set
{ this._query = value; }
}
private void InitializeExceptionQuery()
{
String whereClause = "Filters defined here from user control properties.";
switch (this.ExceptionCategory)
{
case ExceptionCategories.Product:
this.LookupQuery = base.Repository.GetFilteredQuery<ProductException>(this.LookupQuery, whereClause, this.SortField, this.SortDirection).Cast<IExceptionEntity>();
break;
case ExceptionCategories.Part:
this.LookupQuery = base.Repository.GetFilteredQuery<PartException>(this.LookupQuery, whereClause, this.SortField, this.SortDirection).Cast<IExceptionEntity>();
break;
case ExceptionCategories.Rebuild:
this.LookupQuery = base.Repository.GetFilteredQuery<RebuildException>(this.LookupQuery, whereClause, this.SortField, this.SortDirection).Cast<IExceptionEntity>();
break;
case ExceptionCategories.UNKNOWN:
throw new ArgumentException("Exception Category is undefined");
}
}
private void BindQueryResults()
{
switch (this.ExceptionCategory)
{
case ExceptionCategories.Product:
listView.DataSource = this.ExceptionList.Cast<ProductException>();
listView.DataBind();
break;
case ExceptionCategories.Part:
listView.DataSource = this.ExceptionList.Cast<PartException>();
listView.DataBind();
break;
case ExceptionCategories.Rebuild:
listView.DataSource = this.ExceptionList.Cast<RebuildException>();
listView.DataBind();
break;
case ExceptionCategories.UNKNOWN:
throw new ArgumentException("Exception Category is undefined");
}
}
全体的な目標は、ExceptionList プロパティを呼び出して、IExceptionEntity インターフェイスを実装する型の 1 つにキャストできるようにすることです。クエリしている 3 つのエンティティのどれであっても、結果を取得できる単一のポイントがあります。つまり、BindQueryResults() を参照してください。
しかし、そうではありません。これを実行すると、Query をリスト (.ToList()) に変換しようとすると、ExceptionList プロパティが例外をスローします。
Unable to cast the type 'PartException' to type 'IExceptionEntity'. LINQ to Entities only supports casting EDM primitive or enumeration types.
必要に応じて、インターフェイスとそれを実装するクラスを前後にキャストできると思いました。明らかにこれは事実ではなく、理にかなっていると思いますが、私がやろうとしていることを達成する他の方法はありますか? あると信じたい。他の誰かがこれと同じ難問を抱えていますか?
ありがとう、G
更新: 2013-01-22
インターフェイスではなく基本クラスから派生させると、基本クラスから派生クラスに ExceptionList をキャストして、再び元に戻すことができるという印象を受けます。
この目的のために、私は HighCores の提案に従っています。私は持っている ...
- 概念モデル (EDMX) で、3 つの「例外」エンティティ (ProductException、PartException、RebuildException) 間で共有されるすべてのプロパティを含むエンティティが作成されました。「ExceptionBase」と名付けました
- 3 つの例外拡張機能からこれらのフィールドを削除し、「ExceptionBase」から派生させました。
私が今抱えている問題は、各例外エンティティとその基になるテーブルとの間のマッピングが壊れていることです。基本クラスのフィールドを、派生エンティティの基になるテーブルにマップする必要があります。[マッピングの詳細] ウィンドウで、基本クラスから値/プロパティを選択して、それぞれのテーブル列にマップできることを期待していましたが、使用できる値は派生クラスの値のみであり、基本の値ではありません。クラス。
更新: 2013-01-23
結局のところ、私が使用している概念モデルは TPT (Table Per Type 戦略) を使用しています。これが、この方法での継承の実装が機能しない理由です。共通フィールドを継承するには、データベース内の独自のテーブルに分割する必要があります。残念ながら、データベース スキーマは変更できません。
次の記事を参照しました。誰かが役立つことを願っています。
そのため、誰かが追加のアイデアを持っている場合は、これを達成する方法をまだ探しています。さらなる提案を歓迎します.
更新: 2013-01-23
マシューさん、お返事ありがとうございます!私のテーブル構造は次のようになります...
製品例外
- ID [PK]
- 商品名
- 例外メッセージ
- 例外重大度
パーツ例外
- ID [PK]
- 部品名
- 部品メーカー
- 部品原価
- 商品ID [外字]
- 例外メッセージ
- 例外重大度
RebuildException
- ID [PK]
- 再構築の理由
- RebuildManufacturer
- 商品ID [外字]
- 例外メッセージ
- 例外重大度
基本的に、ExceptionMsg、ExceptionSev、および ID(?) を使用して BaseEntity を作成したいと考えています。これらのフィールドは 3 つの Exception エンティティすべてで共有されているためです。
注:この投稿に反対票を投じた人は誰でも説明を提供してもらえますか? 反対票を投じるのは、間違いから学び、それを繰り返さないようにする場合にのみ役立ちます。