Entity Framework: ObjectSet и его (обобщенные) отклонения - PullRequest
4 голосов
/ 14 сентября 2010

Я использую: 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);
    }
}

Если T равно BaseType, это все работает отлично, но: Проблема в том, что в EntityFramework, когда один класс наследует другой, они разделяют ObjectSet, и поэтому, если T равно DerivedType, тогда GetTheObjectSet возвращает ObjectSet<BaseType>, который не может быть приведен к ObjectSet<DerivedType>.

Есть ли способ на самом деле разыграть эту вещь или как-нибудь еще выполнить SingleOrDefault? Могут ли эти вещи быть сотворены с использованием IObjectSet<> и IBaseType?

Ответы [ 3 ]

7 голосов
/ 15 сентября 2010

Я думаю, вы ищете это:

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

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

Метод OfType объекта ObjectQuery (из которого происходит ObjectSet) будет возвращать объекты производного типа.

3 голосов
/ 15 сентября 2010

Ответ на эту проблему был следующим:

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).Спасибо!

1 голос
/ 15 сентября 2010

Я проверил один из моих тестовых проектов, который в настоящее время далек от состояния сборки, но раньше он работал у меня:

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);
    }

    ...
}

Главное, что класс Entity не моделируется в файле EDMX.Все объекты, смоделированные в файле EDMX, имеют свои собственные Id и Timestamp, но мои классы POCO используют общий базовый класс.Я использовал репозиторий без проблем.

...