假设我有以下实体
public abstract class Animal
{
public int Id {get;set;}
}
public class Cat : Animal
{
}
public class Dog : Animal
{
}
是否可以在不创建实例的情况下确定实体的类型。
var id = 1;
var type = context.Animals.GetTypeOfAnimal(id)
public static Type GetTypeOfAnimal(this ObjectSet<Animal> source, int id)
{
// What shall I do here, I dont want to fetch the instance at this point...
var animal = source.First(a => a.Id == id);
return animal.GetType();
}
我考虑使用以下方法的一个解决方案...
public static Type GetTypeOfAnimal(this ObjectSet<Animal> source, int id)
{
var info = source.Where(a => a.Id == id).Select(a => new {IsDog = a is Dog, IsCat = a is Cat}).First();
if(info.IsDog) return typeof(Dog);
if(info.IdCat) return typeof(Cat);
return null;
}
答案 0 :(得分:2)
如果没有查询数据库,就无法获取此信息。您正在使用TPT - 这意味着该数据库包含Animal,Dog和Cat表。数据库中的继承通过Animal和Dog之间以及Animal和Cat之间的一对一关系建模。您要做的最小事情是查询该Id的Animal和Dog表(它只能存在于其中一个中)。第一个问题是您不能直接使用EF查询这些表,因为EF只能与整个实体一起工作(不仅仅是映射到单个表的部分) - 您必须使用直接SQL。第二个问题是这个解决方案的脆弱性。如果添加新的派生实体,则必须修复此查询(对于您的示例也是如此)。
TPT查询速度慢的原因是,EF必须查询所有继承树=在您的案例中Animal
加入Dog
与Animal
连接Cat
加入{{1}}。 .NET 4.5中有一些性能改进可用于查询TPT继承树,但它不会影响您的查询,因为它只需要查询整个结构。