Cast()异常:LINQ to Entities仅支持转换EDM原语或枚举类型

时间:2013-12-31 16:36:01

标签: c# asp.net-mvc entity-framework casting linq-to-entities

我想在我写的通用MVC视图中显示一个名为CriminalEvent的实体。视图要求模型传递给它应实现IDataModel接口。现在,CriminalEvent具有实现此接口的属性,但名称不同,我无法更改。

因此,在我的代码中,我继承了CriminalEvent和我的派生类(也称为CriminalEvent,我想这很愚蠢,但允许我避免许多代码更改...)具有显式接口代码:

Using ViewApp;
public interface IDataModel
{
    int ID { get; set; }
    int CriminalEventID { get; set; }
}

public class ViewCriminalEvent : AIM.Police.DB.CriminalEvent, IDataModel
{
    int IDataModel.ID
    {
        get { return CriminalEventID; }
        set { CriminalEventID = value; }
    }
}

(我知道,在这种情况下,接口的ID属性等于CriminalEventID,它没关系)

我希望能够阅读AIM.Police.DB.CriminalEvent实体并将我的视图模型由Linq填充到Entities Cast(),将它们添加到派生的CriminalEvent,如下所示:

视图模型(我需要填充CriminalEvents属性):

Using ViewApp;
public class CriminalEventMainViewModel
{
    public IEnumerable<IDataModel> CriminalEvents { get; set; }
    public IDataModel SelectedEntity { get; set; }

    public string SubEntityDisplayName { get; set; }

    public IEnumerable<IDataModel> SubEntityCollection { get; set; }
    public IDataModel SelectedSubEntity { get; set; }
}

和Controller代码:

Using ViewApp;    
private ViewResult CriminalEventIndexView(CriminalEvent selectedCriminalEvent = null)
{
    CriminalEventMainViewModel viewModel =
        new CriminalEventMainViewModel();

    using (var db1 = new AIM.Police.DB.InvestigationContext(lazyLoadingEnabled: false))
    {
        viewModel.CriminalEvents = db1.CriminalEvents.Cast<ViewCriminalEvent>().ToList(); // THIS LINE THROWS THE EXCEPTION
        viewModel.SelectedEntity = selectedCriminalEvent;
    }
    return View("Index", (object)viewModel);
}

请注意原始的CriminalEvent类和InvestigationContext都在AIM.Police.DB dll中找不到我无法触及

错误:

Unable to cast the type 'AIM.Police.DB.CriminalEvent' to type 'InvestigationSimulator.Models.CriminalEvent'. LINQ to Entities only supports casting EDM primitive or enumeration types.

为什么会出现此错误? 我的方法备注总是受欢迎的。

3 个答案:

答案 0 :(得分:3)

由于您获得了所有实体,因此可以先实现查询,然后执行转换。

这将执行内存中的强制转换,而不是尝试将其作为查询转换的一部分进行表达。之所以出现此错误,是因为LINQ to Entities不支持将SQL转换为非实体类,即使它是从实体类继承的,因为没有将其他列映射到SELECT语句。通过实现数据,然后在内存中执行Cast(LINQ to Objects),可以避免转换错误。

但是,在您的情况下,您可以向后继承这项工作。为了使其工作,我建议让数据库模型实现IDataModel并完全避免强制转换,请参阅http://msdn.microsoft.com/en-us/library/vstudio/bb738696(v=vs.100).aspxhttp://msdn.microsoft.com/en-us/library/wa80x488.aspx。特别是,你的部分类可以实现接口(老实说,不记得设计者是否允许你添加接口定义,因为我现在只做代码优先)。请注意,可能完全不需要您的视图特定模型。

viewModel.CriminalEvents = db1.CriminalEvents.ToList();

我可能会做的另一种选择是保持视图模型完全分离(不要让它继承实体类)并使用AutoMapper在它们之间进行映射。

var criminalEvents = db1.CriminalEvents.ToList();
viewModel.CriminalEvents = Mapper.Map<CriminalEventViewModel>(criminalEvents);

答案 1 :(得分:2)

Enumerable.Cast<TResult>正在尝试转换集合中的每个元素。它在你的场景中失败(毫不奇怪),因为你试图将AIM.Police.DB.CriminalEvent)类的实例强制转换为 child 的对象({{1} })类。你不能用C#进行这样的演员。

为了解决这个问题,您需要先从数据库加载对象,然后将它们手动转换(映射)到您的Model类。最简单的代码是这样的:

InvestigationSimulator.Models.CriminalEvent

答案 2 :(得分:0)

在ToList()或Single()

之后使用强制转换
_c.Customers.ToList().Cast<CustomerBinding>()