1

私は、データベースから情報を取得してユーザーに表示するだけのアプリケーションの一部に取り組んでいます。簡単にするために、2つのテーブルを持つデータベースがあると仮定しCatsますDogs。両方のテーブルに手動で主キーが割り当てられており、重複/重複することはありません。私が達成しようとしている目標は、concat両方のテーブルを処理する1つのLINQクエリを実行することです。

私は最近、コードで手動で作成されたオブジェクトの2つのコレクションとの実行に関してこの質問をしました。前の質問を読むことをお勧めします。これは、この質問に多くの洞察を与えるからです。LINQ concatCatsDogs

インターフェイスを使用したい理由は、クエリを単純化するためです。.Select私は現在、必要な各列を匿名タイプにするソリューションを持っています。これはこのインスタンスでは正常に機能しますが、使用しているデータを含むページを消費します。

前の質問と今回の質問の違いは、これらの動物をデータベースから取得しようとしていることです。私の分析から、私を私に関連付けることができない.NETか、できないようですEntity Frameworkdatabaseinterface

モデル(古い質問から)

public interface iAnimal
{
    string name { get; set; }
    int age { get; set; }
}
public class Dog :iAnimal
{
    public string name { get; set; }
    public int age { get; set; }
}
public class Cat:iAnimal
{
    public string name { get; set; }
    public int age { get; set; }
}

LINQこれが私が試したいくつかの異なるクエリと結果のエラーです。最初の例は、前の質問のソリューションを使用することです。

var model = _db.Cats.Concat<iAnimal>(_db.Dogs).Take(4);

System.ArgumentException: DbUnionAllExpression requires arguments with compatible collection ResultTypes.

共分散なし:

var model = _db.Cats.Cast<iAnimal>().Concat(_db.Dogs.Cast<iAnimal>());

System.NotSupportedException: Unable to cast the type 'Test.Models.Cat' to type 'Test.Interfaces.iAnimals'. LINQ to Entities only supports casting Entity Data Model primitive types.

上記のエラーから、特定のテーブルにマップされていないため、インターフェイスを使用してデータベースを操作できないようです。

任意の洞察をいただければ幸いです。ありがとう

編集 @ReedCopseyに応答して、あなたの解決策で、私は私の例と同じエラーを受け取りますwithout covariance。エラーが推奨するものと一致するようにビューのタイプを変更しようとしましたが、その結果、このエラーが発生しました

System.InvalidOperationException: The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery`1[Test.Interfaces.iAnimal]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[Test.Models.Cat]'.
4

1 に答える 1

1

あなたのデータベースはあなたのインターフェースについて何も知らないので、おそらくこれを機能させることはできないでしょう。2つの選択肢があります。

継承(たとえば、Entity Frameworkでサポートされている)を使用して、共通のベースエンティティから両方のエンティティを継承できます。基本タイプに対してクエリを実行できるようになりますが、データベースレベルで継承を実装する方法によっては、データモデルの変更が必要になる場合があります。

TPT継承TPH継承のドキュメントをご覧ください。TPC継承のような他の継承モデルはまだありますが、現在、デザイナーのサポートが不足しています。

2番目のオプションは、両方のテーブルから結果をメモリにフェッチし、LINQtoObjectsを使用してそれらを単一のコレクションにマージすることです。

var dogs = database.Dogs.Take(4).ToList();
var cats = database.Cats.Take(4).ToList();

var pets = dogs.Cast<IPet>().Concat(cats).ToList();

また、クエリに注意してください

var model = _db.Cats.Concat<iAnimal>(_db.Dogs).Take(4);

あまりうまく設計されていないようです。結果は使用するデータベースによって異なりますが、通常は最初の4匹の猫を飼い、犬を見たことがなくても驚かないでしょう。

于 2013-01-08T19:47:41.457 に答える