4

私が使用するもの:EntityFramework + POCO

これがそのことです:

public interface IBaseType
{
    int Id { get; set; }
}

public class BaseType : IBaseType
{
    public virtual int Id { get; set; }
}

public class DerivedType : BaseType
{
}

問題:

public class EntityFetcher<T> where T : BaseType
{
    public object GetById(int id)
    {
        ObjectSet<T> objectSet = (ObjectSet<T>)GetTheObjectSet(typeof(T)); 

        return objectSet.SingleOrDefault((o) => o.Id == id);
    }
}

これTBaseTypeすべて完全に機能しますが、問題は、EntityFrameworkで、あるクラスが別のクラスを継承するObjectSetと、を共有するため、がそうである場合TDerivedType、にキャストできない戻り値をGetTheObjectSet返すことです。ObjectSet<BaseType>ObjectSet<DerivedType>

これを実際にキャストする方法はありますか、それとも他の方法で実行する方法はありSingleOrDefaultますか?IObjectSet<>とを使用してそれらをキャストできますIBaseTypeか?

4

3 に答える 3

7

私はあなたがこれを探していると思います:

public T GetById(int id)
{
    ObjectSet<T> objectSet = (ObjectSet<T>)GetTheObjectSet(typeof(T)); 

    return objectSet.OfType<T>().SingleOrDefault((o) => o.Id == id);
}

ObjectQuery(ObjectSetの派生元)のOfTypeメソッドは、派生型のオブジェクトを返します。

于 2010-09-14T20:35:07.360 に答える
3

このキャストの問題に対する答えは次のとおりです。

public T GetById(int id)
{
    // The line that throws InvalidCast with T = DerivedType
    //ObjectSet<T> objectSet = (ObjectSet<T>)GetTheObjectSet(typeof(T));

    // This is a valid cast since ObjectSet<T> is derived from ObjectQuery
    ObjectQuery objectQuery = (ObjectQuery)GetTheObjectSet(typeof(T));
    return objectQuery.OfType<T>().SingleOrDefault((e) => e.Id == id);
}

解決策は、ObjectSetをObjectQueryにキャストし、そこでクエリを実行することでした。ここで最も重要な部分は、ObjectQueryがジェネリックではないため、キャストが正常に行われることです。

ベナー・マッカーシーは、OfType + ObjectQueryへのキャスト(ObjectSet:ObjectQueryという事実)を私に指摘してくれたので、私はいくつかの功績を認めなければなりません。ありがとう!

于 2010-09-15T06:12:57.350 に答える
1

私は現在ビルド可能な状態から遠く離れている私のテストプロジェクトの1つをチェックしましたが、これは以前はうまくいきました:

public interface IEntity
{
    int Id { get; }
    byte[] Timestamp { get; set; }
}

public abstract class Entity : IEntity
{
    public int Id { get; set; }
    public byte[] Timestamp { get; set; }
}

public class PocoData : Entity
{
   ...
}

public class Repository<T> : IRepository<T> where T : class, IEntity 
{
    protected ObjectContext Context;
    protected ObjectSet<T> ObjectSet;

    public Repository(ObjectContext context)
    {
        Context = context;
        ObjectSet = context.CreateObjectSet<T>();
    }

    public virtual T GetById(int id)
    {
        return ObjectSet.SingleOrDefault(o => o.Id == id);
    }

    ...
}

重要な点は、エンティティクラスがEDMXファイルでモデル化されていないことです。EDMXファイルでモデル化されたすべてのエンティティには独自のIDとタイムスタンプがありますが、私のPOCOクラスは共有基本クラスを使用しています。リポジトリ<PocoData>を問題なく使用しました。

于 2010-09-14T20:30:23.060 に答える