2012-06-27 64 views
7

可以说我有以下实体返回实体类型使用每个类型继承表时

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; 
} 
+1

我不认为你可以。 – Yeonho

+0

设计也有点味道;查询泛型类型的特定子类型,然后分支,可能应该用多态性代替。 – millimoose

+0

在您评论的位置,来源已被提取。那是你想要阻止的吗?编辑:不,现在我明白了。现在思考时间。 – Michael

回答

2

有没有办法让没有查询到该数据库的信息。您正在使用TPT - 这意味着该数据库包含Animal,Dog和Cat表格。数据库中的继承是通过动物与狗之间以及动物与猫之间的一对一关系建模的。你必须做的至少是为这个Id查询Animal和Dog表(它只能存在于其中的一个表中)。第一个问题是,您无法直接使用EF查询这些表,因为EF只能与整个实体一起工作(不仅将零件映射到单个表) - 您必须使用直接SQL。第二个问题是这个解决方案的脆弱性。如果您添加新派生实体,则必须修复此查询(对于您的示例,也是如此)。

为什么TPT的查询很慢的原因是,EF必须查询所有继承树=与Dog串联起来Animal加入了与Cat加入你的情况Animal。在.NET 4.5中查询TPT继承树时有一些性能改进,但它不会影响您的查询,因为它只需查询整个结构。

+0

只是出于好奇:你可以通过使用只使用'Animal'中定义的属性的投影来避免这种惩罚? – millimoose