Entity Framework LINQ を使用して、すべての親テーブルの親クラスを返し、型がインターフェイスであるプロパティに、インターフェイスの複数の具象実装の 1 つを親クラスに設定したいと考えています。親テーブルのフィールドの値に基づいて、クエリ時にどの具体的な実装を決定する必要があるか。
非常に単純化した例では、3 つのテーブルと 3 つの対応する POCO があります。
例のための簡単な表
例のための単純なクラス
internal interface IConfiguration
{
}
internal class ConfigurationContainer
{
public IConfiguration Config { get; set; }
}
internal class ConfigurationSouth : IConfiguration
{
}
internal class ConfigurationNorth : IConfiguration
{
}
残念ながら、すべての親の結果をループして、ループ内で使用するサブクエリを決定します。このブロックのようなもの。
foreach (var configMaster in db.ConfigMasters.ToList())
{
var configContainer = new ConfigurationContainer();
if (configMaster.IsNorth)
configContainer.Config = (from x in db.ConfigNorths
select new ConfigurationNorth())
.FirstOrDefault();
else
configContainer.Config = (from x in db.ConfigSouths
select new ConfigurationSouth())
.FirstOrDefault();
}
サブクエリを実行するために各親レコードをループすることは、最適とは言えません。私は、EF LINQ がデータベースへの 1 回の旅行でクエリを実行し、POCO への射影を実行することを本当に望んでいます。
この LINQ を思いついたのは、1 回の旅行でデータベースにクエリを実行し、クエリ時に 2 つのサブクエリのいずれかによって Config プロパティが設定されるように、投影されたオブジェクトを返すことです。コンパイルされますが、実行時に例外がスローされます。
using (var db = new Entities())
{
var qry = from cfgMaster in db.ConfigMasters
let configNorth = (from x in db.ConfigNorths
select new ConfigurationNorth())
.FirstOrDefault()
let configSouth = (from x in db.ConfigSouths
select new ConfigurationSouth())
.FirstOrDefault()
select new ConfigurationContainer()
{
Config = cfgMaster.IsNorth ? configNorth : (IConfiguration) configSouth
};
var results = qry.ToList();
}
例外
未処理の例外: System.NotSupportedException: タイプ 'EFTest.ConfigurationNorth' をタイプ 'EFTest.IConfiguration' にキャストできません。LINQ to Entities は、Entity Data Model プリミティブ型のキャストのみをサポートします。