3

我需要这个 linq 查询才能工作,但 linq 抱怨 customercontact 和 phone 是 int64s,我还需要连接第二列,但恐怕出于同样的原因这不起作用。如果我添加一个 tostring() 它只是说 linq 无法识别它。

base {System.SystemException} = {“无法将类型 'System.Int64' 转换为类型 'System.Object'。LINQ to Entities 仅支持转换 EDM 基元或枚举类型。”}

var tempCustomers =
                    from c in db.Customers
                    let cc = db.CustomerContacts.FirstOrDefault(x => x.CustomerID == c.CustomerID)
                    select new{cc.CustomerContactID, CustomerValue = c.CustomerName + " 	 	 " + cc.Phone};
4

2 回答 2

1

此错误来自 LINQ 到实体。这是一种解决方案:

var tempCustomers =
    from c in db.Customers.ToArray()
    let cc = db.CustomerContacts
       .FirstOrDefault(x => x.CustomerID == c.CustomerID)
    select new
    {
        cc.CustomerContactID,
        CustomerValue = string.Format("{0} 	 	 {0}",
            c.CustomerName, cc.Phone)
    };

以上将在尝试进行字符串连接之前访问数据库。如果这是不可接受的,请在您的问题中注明。

为什么它不起作用

LINQ to Entities 使用延迟 SQL 执行,这意味着您的 LINQ 查询将不会访问数据库,直到您使用 foreach 迭代或IQueryable调用类似. 您可以在 LINQ 谓词表达式中使用您想要的任何代码,但如果 LINQ to Entities 无法弄清楚如何将其转换为 SQL,它将在运行时失败。您的代码失败,因为 LINQ to Entities 在运行 SQL 查询时无法弄清楚如何连接 CustomerName、您的自定义字符串和 PhoneNumber。上面的工作是因为它首先从数据库中获取数据,然后在内存中进行字符串连接。ToListToArrayIQueryable

更新

要扩展 @JeffMercado 击败我的更好的解决方案,您真的应该使用导航属性来加入CustomerCustomerContacts. 这将消除对let子句和FirstorFirstOrDefault调用的需要:

public class Customer
{
    public long CustomerID { get; set; }
    public string CustomerName { get; set; }
    public virtual ICollection<CustomerContact> Contacts { get; set; }
}

public class CustomerContact
{
    public long CustomerContactID { get; set; }
    public long CustomerID { get; set; }
    public virtual Customer Owner { get; set; }
    public long Phone { get; set; } // I agree this should be a string
}

然后,您应该能够像这样查询数据:

var query = db.CustomerContacts
    .Include(x => x.Owner) // eager load to avoid multiple separate SQL queries
    .Select(x => new {
        CustomerContactID = x.CustomerContactID,
        CustomerName = x.Owner.CustomerName,
        Phone = x.Phone,
});

从这里,您可以使用AsEnumerableToArrayToList来执行查询并格式化您的特殊CustomerValue属性。

var results = query
    .ToArray() // or .AsEnumerable(), or .ToList(), all will execute the SQL query
    .Select(x => new {
        CustomerContactId = x.CustomerContactID,
        CustomerValue = string.Format("{0} &#09;&emsp;&#09; {1}",
            x.CustomerName, x.Phone)
});
于 2013-04-07T00:16:18.647 回答
0

您可以在查询中执行的操作类型在 EF 中是有限的,转换就是其中之一。您需要将该部分移出查询,然后获取数据然后使用AsEnumerable(),以便使用 LINQ to Objects。然后你可以对数据做任何你想做的事情。

var query=
    from c in db.Customers
    let cc = c.CustomerContacts.FirstOrDefault() // better to use the navigation properties instead
    select new // select the fields you need
    {
        cc.CustomerContactId,
        c.CustomerName,
        Phone = (long?)cc.Phone, // cc could potentially be null this long must also be nullable
    };
var tempCustomers =
    from x in query.AsEnumerable() // LINQ to Objects
    select new // now you can do what you want to the data
    {
        x.CustomerContactId,
        CustomerValue = x.CustomerName + " &#09;&emsp;&#09; " + x.Phone,
    };

为了便于阅读,我将它们分成单独的语句,但如果你愿意,你可以将它们组合起来。

于 2013-04-07T00:27:11.937 回答