【问题标题】:Linq To Entities 'Only primitive types or enumeration types are supported' ErrorLinq To Entities“仅支持原始类型或枚举类型”错误
【发布时间】:2013-03-13 14:10:22
【问题描述】:

我正在使用 LinqPad 来测试我的查询。此查询在 LInqPad 连接到我的数据库(LInq 到 SQL)时有效,但当我将连接更改为使用我的 Entity Framework 5 Model.dll 时它不起作用。 (链接到实体)。这是在 C# 中。

我有两个名为 Plan 和 PlanDetails 的表。关系是一个计划对多个计划细节。

var q = from pd in PlanDetails
        select new {
            pd.PlanDetailID,
            ThePlanName = (from p in this.Plans
                    where p.PlanID == pd.PlanID
                    select p.PlanName)
        };
var results = q.ToList();
q.Dump(); //This is a linqpad method to output the result.

我收到此错误“NotSupportedException:无法创建类型为“Domain.Data.Plan”的常量值。在此上下文中仅支持原始类型或枚举类型。”任何想法为什么这只适用于 Linq to SQL?

【问题讨论】:

    标签: linq c#-4.0 linq-to-sql linq-to-entities entity-framework-5


    【解决方案1】:

    如果关系已经存在。

    为什么不直接说。

    var q = from pd in PlanDetails
            select new {
                pd.PlanDetailID,
                ThePlanName = pd.Plan.PlanName
            };
    

    当然,我假设每个 PlanDetail 都属于一个计划。

    更新

    要从 LinqPad 获得更好的结果,您可以告诉它使用您自己的程序集(其中包含您的 DbContext)而不是它使用的默认 Datacontext。

    【讨论】:

    • 你说的太对了。我完全忘记了 Navigational 属性。你能告诉我刚开始使用EF吗?谢谢!
    【解决方案2】:

    基本上,这意味着您在查询中使用了一些复杂的数据类型进行比较。 在你的情况下,我怀疑from p in this.Plans where p.PlanID == pd.PlanID 是罪魁祸首。

    而且它依赖于 DataProvider。它可能适用于Sql Data Provider,但不适用于SqlCE data Provider等。

    您应该做的是将您的 this.Plans 集合转换为仅包含 Id 的原始类型集合,即

    var integers = PlanDetails.Plans.Select(s=>s.Id).ToList();
    

    然后在里面使用这个列表。

    var q = from pd in PlanDetails
            select new {
                pd.PlanDetailID,
                ThePlanName = (from p in integers
                        where p == pd.PlanID
                        select pd.PlanName)
            };
    

    【讨论】:

    • 当他说 One Plan to Many PlanDetails 时,我担心他为什么需要进行嵌套查询 .. 这意味着 PlanDetails 不能单独存在 .. 它们必须与 Plan 相关联。 .. 所以如果你有一个 PlanDetail 它应该有一个名为 Plan 的导航属性(如果没有重命名)
    • 没错,他不需要做条件,而是为了这个错误。
    • 谢谢!我一直在玩EF,这也很有意义。我将在两个不相关的实体上尝试一下。
    • 我同意,但是虽然这解决了手头的错误,但它并没有解释它。这是一个 Linqpad 故障,无论你怎么看。
    • 这不是 Linqpad 故障,或者它不仅是 linqqpad 故障,请尝试使用 .sdf 文件作为数据源的相同代码,所以无论是什么原因,解决方案是在单独的文件中提取比较值原始列表并在里面使用这个列表。 :)。
    【解决方案3】:

    如果您喜欢(或特殊性),这是一个 Linqpad 错误。我自己也发现了类似的行为。像我一样,您可能会发现您的查询适用于ObjectContext,但不适用于DbContext。 (它在 Visual Studio 中工作)。

    我认为这与 Linqpad 的内部结构有关。它将MergeAs (AppendOnly) 添加到集合中,上下文是UserQuery,它可能包含一些导致此错误的代码。

    当您在 Linqpad 代码中创建新的上下文实例并针对该实例运行查询时,代码确实工作这一事实证实了这一点。

    【讨论】:

    • 您的回答对我帮助很大!即使使用更简单的“选择新”子句,我也遇到了类似的问题,在该子句中,我只是创建了自己的类的实例,其属性是对实体的引用(没有另一个嵌套的“来自”子句)。使用我自己的上下文实例,它也可以在 LINQPad 中工作(就像在 VS 中所做的那样)。
    【解决方案4】:

    当我尝试对实体框架表达式中的导航属性进行空检查时遇到此错误

    我通过不使用表达式中的非空检查而仅使用 Any() 函数来解决它。

      protected Expression<Func<Entities.Employee, bool>> BriefShouldAppearInSearchResults(
            IQueryable<Entities.Employee> briefs, string username)
        {
           var trimmedUsername = NameHelper.GetFormattedName(username);
    
            Expression<Func<Entities.Employee, bool>> filterExpression = cse =>                
                 cse.Employee.Cars.All(c => 
                     c.Employee.Cars!=null &&  <--Removing this line resolved my issue
                     c.Employee.Cars.Any(cur => cur.CarMake =="Benz")));
    
            return filterExpression;
        }
    

    希望这对某人有所帮助!

    【讨论】:

    • 这为我解决了,谢谢!我删除了空检查并使用了 Any()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多