我使用: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
投射这些内容吗?
答案 0 :(得分:7)
我认为你正在寻找这个:
public T GetById(int id)
{
ObjectSet<T> objectSet = (ObjectSet<T>)GetTheObjectSet(typeof(T));
return objectSet.OfType<T>().SingleOrDefault((o) => o.Id == id);
}
OfType method of an ObjectQuery(ObjectSet派生自)将返回派生类型的对象。
答案 1 :(得分: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)。谢谢!
答案 2 :(得分: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);
}
...
}
重点是Entity类未在EDMX文件中建模。在EDMX文件中建模的所有实体都有自己的Id和Timestamp,但我的POCO类使用共享基类。我使用了Repository&lt; PocoData&gt;没有任何问题。