当EntityFramework
执行LINQ
查询时,如果查询将某些东西作为动态类返回,则无法获得实际类型的结果。
我有一个抽象类:
abstract class Person
{
public string Name { get; set; }
//and about 1000 other properties
}
和2个派生类:
class RealPerson : Person
{
public void Print()
{
Console.WriteLine("Type=RealPerson, Name=" + Name);
}
}
class LegalPerson : Person
{
public void Print()
{
Console.WriteLine("Type=LegalPerson, Name=" + Name);
}
}
我的LINQ TO SQL
查询:
var lst =
EFContext.Persons.Select(item=> new { DynamicClass_Name = item.Name }).ToList();
现在,对于lst中的每个项目,我需要知道其类的类型以将此项目转换为该类型,但item.GetType()
返回动态类型。
例如,假设lst的一个项目是RealPerson
(称为dynamicTypeItem),所以如果我知道它的类型是RealPerson
,我将使用以下代码将此dynamicTypeItem强制转换为RealPerson
:
var value = dynamicTypeItem.GetType().GetProperty("DynamicClass_Name").GetValue(dynamicTypeItem);
var result = (RealPerson)Activator.CreateInstance(typeof(RealPerson));
result.GetType().GetProperty("Name").SetValue(result, value);
但是我不知道这个dynamicTypeItem的类型(它有一个动态类型); 如何实现lst的每个项目的类型? 上面的查询只选择实体的1个属性(Name属性)是非常重要的,所以我不能使用这个代码:
var lst =
EFContext.Persons.ToList().Select(item=> new { DynamicClass_Name = item.Name, Type=item.GetType() });
所以在将此项目转换为动态类型之前,我需要知道lst的每个项目的类型。
EDIT1
更多解释:结果不能是Person
,因为Person
是抽象的。结果为RealPerson
或LegalPerson
,当我在转换期间仅选择RealPerson
或LegalPerson
中的一个属性时,强类型为匿名类型时,将错过原始实体的类型。
答案 0 :(得分:2)
您想从数据库表的一个属性的值中引出类型吗?无法从中选择类型,因为未从数据库中提取类型信息。
如果你解释它真正需要什么,我们仍然可以帮助你,但这个约束:
上述查询仅选择实体
的1个属性(Name属性)非常重要
使你想要实现的目标变得不可能。您必须从数据库中选择更多内容。
我如何成像这样做,虽然如果可能的话我会首先看看数据库设计:
public partial class Person {
public Person() {
_dotnetType = this.GetType().Fullname;
_dotnetAssembly = this.GetType().Assembly.Fullname;
}
private string _dotnetType;
private string _dotnetAssembly;
public string DotNetType { get { return _dotnetType; } set { _dotnetType = value } }
public string DotNetAssembly { get { return _dotnetAssembl; } set { _dotnetAssembly = value } }
}
// Example usage
var peeps = from person in Entities.Persons
select new { Name = person.Name, Type = DotNetType, Assembly = DotNetAssembly };
var loadedPeople = peeps.ToList() // enumerate it
.Select( p => {
var instance = Activator.CreateInstance(p.Assembly, p.Type);
var property = p.GetType().GetProperties().First(prop => prop.Name == "Name");
property.SetValue(instance, p.Name, null);
});
我没有尝试过这段代码,但它应该可以工作,只需确保调用Person
中的无参数构造函数。关键是数据库将“丢失”类型信息,因此最好将其存储为字符串。请记住,您还需要将列添加到数据库并映射它们!
答案 1 :(得分:1)
这看起来像是一个XY问题。您的问题是,如何使用实体框架(AND NOT Linq To SQL)从表中实现对象,我有一个鉴别器?
答案很简单。
你不要!
对您的Entity Framework模型使用Single Table inheritance,您的LinqToEntities查询非常简单。
一旦你有了这个,那绝对没有理由为你的投射做什么。
您应该考虑对象而不是ORM表。
因此,您可以执行以下操作以获取所有LegalPersons的名称' Alice'
var legallyAlices = EFContext.Persons.OfType<LegalPerson>()
.Where(x => x.Name == 'Alice');
OR
var legallyAlices = from legalPerson in EFContext.Persons.OfType<LegalPerson>()
where legalPerson.Name == 'Alice'
select legalPerson;