我需要这个linq查询才能工作但是linq抱怨客户联系和手机是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};
答案 0 :(得分: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执行,这意味着在使用foreach迭代IQueryable
或调用ToList
或{{1}之类的方法之前,LINQ查询不会访问数据库在ToArray
上。您可以在LINQ谓词表达式中使用您想要的任何代码,但如果LINQ to Entities无法弄清楚如何将其转换为SQL,它将在运行时失败。您的代码失败,因为LINQ to Entities无法在运行SQL查询时弄清楚如何连接CustomerName,您的自定义字符串和PhoneNumber。上面的工作原理是因为它首先从数据库获取数据然后在内存中进行字符串连接。
<强>更新强>
为了扩展@JeffMercado击败我的更好的解决方案,你真的应该使用导航属性加入IQueryable
和Customer
。这样就无需CustomerContacts
子句和let
或First
来电:
FirstOrDefault
然后您应该能够查询出这样的数据:
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,
});
,AsEnumerable
或ToArray
来执行查询并设置特殊ToList
属性的格式。
CustomerValue
答案 1 :(得分: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 + " 	 	 " + x.Phone,
};
为了便于阅读,我打破了单独的声明,但如果你愿意的话,你可以把它们结合起来。