无法将类型'System.Int64'转换为类型'System.Object'。LINQ to Entities仅支持转换实体数据模型基元类型。

9

我创建了一个使用EF 4C#的程序来获取一些数据。我使用Linq,代码如下:

    public List<object> GenerateCallTrackingReport(int startRowIndex, int maximumRows, int createdByID)
    {
        var query = from c in this.ObjectContext.CallLogs                        
                    select new
                    {
                        CallLogID = c.CallLogID,
                        DomainName = c.CallDomain.FullName,
                        CreatedByID = c.CreatedByID,
                        CreatedBy = c.CreatedByUser.FirstName + " " + c.CreatedByUser.LastAccessIPN,
                        CalledOn = c.CallDate,
                        IssueResolutionTime = c.IssueResolutionTime,                            
                        CallType = c.CallType.FullName,
                        CallDescription = c.CallDescription,
                        CustomerName = (c.CustomerID > 0 ? c.Customer.FirstName + " " + c.Customer.LastAccessIPN : c.TempCaller.FirstName + " " + c.TempCaller.LastName),
                        CustomerEmail = (c.CustomerID > 0 ? c.Customer.Email : string.Empty),
                        CustomerResponse = c.Response.FullName,
                        IsPending = c.IsPending,
                        NeedFurtherContact = c.NeedFurtherContact
                    };

        if (createdByID > 0)
            query = query.Where(c => c.CreatedByID == createdByID);

        if (maximumRows > 0)
            query = query.Skip(startRowIndex).Take(maximumRows);

        return query.ToList<object>();

    }

这会导致以下错误:
Unable to cast the type 'System.Int64' to type 'System.Object'. LINQ to Entities only supports casting Entity Data Model primitive types.

有什么想法,我为什么会出现这个错误?谢谢。

1
异常出现在哪一行? - Christopher Rathermel
1
由于Linq-To-EF的工作方式,无论问题源在哪里,异常可能会在最后一行发生,并且基本上没有用处。 - millimoose
3个回答

5

已解决

我遇到了两个问题,它们中的每一个都会导致这个错误:

1. 我在没有检查实体属性是否有值的情况下访问了可空实体属性。比如说CustomerID可空的,所以我的查询变成了这样!

    var query = from c in this.ObjectContext.CallLogs                        
                select new
                {
                    CallDescription = c.CallDescription,
                    CustomerID = c.CustomerID.HasValue ? c.CustomerID.Value : 0,
                    CustomerName = c.CustomerID.HasValue ? c.Customer.Name : ""
                };

    if (maximumRows > 0)
        query = query.Skip(startRowIndex).Take(maximumRows);

    return query.ToList<object>();

在访问任何空值之前,请通过其HasValue属性检查它(选择部分的第2行)。

2. 我也试图在选择语句中将整数转换为字符串。所以我决定在HTML中进行转换,而不是直接在这里进行转换。这解决了我的问题。

希望这能帮助到某些人!


是的 :) 我明白了并且实现了。谢谢Amir。:). 我的问题也是一样的。1和2。?可以用于1,'SqlFunctions.StringConvert'可以帮助转换为字符串。谢谢 :) - kbvishnu

5

一旦你到达ToList调用,你希望在C#中执行它,而不是在数据库中执行。使用AsEnumerable作为一种方式来表明,“停止在数据库中执行这些操作,在C#中执行它们。”

在最后的ToList之前添加它,以便其他所有操作都在数据库中完成。


0

首先,我不会像你在C#中做的那样,在整个数据表中进行查询。像这样链接linq到entities方法会使它更快- 当您有大量数据集时,速度会非常快:

this.ObjectContext.CallLogs
    .Where(c => c.CreatedByID == createdByID)
    .Skip(startRowIndex)
    .Take(maximumRows)
    .Select(new
        {
                        CallLogID = c.CallLogID,
                        DomainName = c.CallDomain.FullName,
                        CreatedByID = c.CreatedByID,
                        CreatedBy = c.CreatedByUser.FirstName + " " + c.CreatedByUser.LastAccessIPN,
                        CalledOn = c.CallDate,
                        IssueResolutionTime = c.IssueResolutionTime,                            
                        CallType = c.CallType.FullName,
                        CallDescription = c.CallDescription,
                        CustomerName = (c.CustomerID > 0 ? c.Customer.FirstName + " " + c.Customer.LastAccessIPN : c.TempCaller.FirstName + " " + c.TempCaller.LastName),
                        CustomerEmail = (c.CustomerID > 0 ? c.Customer.Email : string.Empty),
                        CustomerResponse = c.Response.FullName,
                        IsPending = c.IsPending,
                        NeedFurtherContact = c.NeedFurtherContact
        })
    .ToList();

其次,我不知道具体的问题,但是像这样创建动态对象列表并不是一个好主意。请创建一个名为CallLogModel的类,并将您要放入对象中的属性放入其中:

.Select(new CallLogModel
        {
                        CallLogID = c.CallLogID,
                        DomainName = c.CallDomain.FullName,
                        CreatedByID = c.CreatedByID,
                        CreatedBy = c.CreatedByUser.FirstName + " " + c.CreatedByUser.LastAccessIPN,
                        CalledOn = c.CallDate,
                        IssueResolutionTime = c.IssueResolutionTime,                            
                        CallType = c.CallType.FullName,
                        CallDescription = c.CallDescription,
                        CustomerName = (c.CustomerID > 0 ? c.Customer.FirstName + " " + c.Customer.LastAccessIPN : c.TempCaller.FirstName + " " + c.TempCaller.LastName),
                        CustomerEmail = (c.CustomerID > 0 ? c.Customer.Email : string.Empty),
                        CustomerResponse = c.Response.FullName,
                        IsPending = c.IsPending,
                        NeedFurtherContact = c.NeedFurtherContact
        })

1
-1 OP的代码只会执行一个查询,它不会获取所有数据然后在客户端进行过滤。你的代码并没有执行完全相同的查询,所以它甚至没有什么帮助。这就是LINQ的真正强大之处——它是一个查询,而不是一组数据。这意味着您可以有条件地向查询中添加操作,就像OP所做的那样。他甚至将变量命名为“查询”而不是“数据”,以反映这种区别。最后,OP的问题(你没有解决)完全是因为整个问题都试图由数据库来解决,而数据库无法将任何东西转换为ToList。 - Servy
关于创建新类型而不是返回“object”的问题,我同意这可能是最好的选择,但这只是一个评论,而不是解决问题的答案。 - Servy
公正的评论,我想我需要更深入地了解LINQ,因为我的先前假设是错误的 - 你每天都会学到新东西 :) - jcvandan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接