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,因此,如果TDerivedTypeGetTheObjectSet返回ObjectSet<BaseType>,不能强制转换为ObjectSet<DerivedType>.

有没有办法实际施放这个东西或以其他方式执行SingleOrDefault?可以使用IObjectSet<>and投射这些东西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不是通用的,所以演员表很好。

我必须感谢 Bennor McCarthy,因为他是指点我 OfType + 强制转换为 ObjectQuery(ObjectSet : ObjectQuery 的事实)的人。谢谢!

于 2010-09-15T06:12:57.350 回答
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 类使用共享基类。我使用 Repository<PocoData> 没有任何问题。

于 2010-09-14T20:30:23.060 回答