geoStartLoc以这种格式“54.5,44.5”保存字符串。我试图将结果拆分并存储在纬度和经度中。我收到以下错误 LINQ to Entities无法识别方法'System.String [] Split(Char [])'方法,而且此方法无法转换为商店表达式。 (选择陈述)
var data = from UberTrip in db.UberTrips
group UberTrip by new { UberTrip.startLoc, UberTrip.geoStartLoc }
into startLocGroup
select new LocationGroup() {
startLocation = startLocGroup.Key.startLoc,
latitude = startLocGroup.Key.geoStartLoc.Split(',').Count().ToString(),
//longitude= startLocGroup.Key.
countTrips = startLocGroup.Count()
};
答案 0 :(得分:1)
这是数据库中的架构问题。在列中存储分隔值是很糟糕的。您应该有两列:一列用于geoLatitude
,另一列用于geoLongitude
。
但是,由于您可能无法自行进行更改,因此您需要确保将数据下拉到程序代码中,然后将其拆分。现在,linq正在尝试使用此代码创建的表达式树并将其转换为SQL查询,并且它无法为Split()
调用执行此操作,因为并非所有受支持的数据库目标都具有类似的Split方法。在将数据加载到程序中的内存之后,需要保存该部分。
要完成此操作,只需检索完整的geoStartLoc
字符串(如果必须,请转换为匿名类型),使用.ToList()
强制查询编译并检索所有数据,然后使用{ {1}}转换为.Select()
个对象。
答案 1 :(得分:0)
每当收到此错误消息时,您都在执行查询AsQueryable
而不是AsEnumerable
。
主要区别在于AsQueryable
通常会在数据库等其他流程中执行,而AsEnumerable
将在您的流程中在内存中执行。
IEnumerable对象知道如何创建Enumerator
。一个枚举器,知道如何做两件事:"给我序列的第一个元素","给我序列的下一个元素(如果没有下一个元素,则为null)。
如果您的查询是AsEnumerable
,它知道可以使用您的流程中的所有类和数据来创建枚举器。因此它可以调用String.Split等函数。
AsQueryable
不包含创建枚举数的所有数据,它包含表达式和Provider
。提供者知道需要在哪里执行查询(通常是数据库,但它也可以是json字符串或Web服务),并且它知道如何将Expression
转换为执行者理解的格式。在您的情况下,Provider
知道如何将Expression
转换为适合您的数据库的SQL语句。
当然,SQL不知道你自己定义的函数。虽然有很多.NET函数可以转换为SQL,但并不是每个函数都可以。 String.Split就是其中之一。
请参阅:Supported and Unsupported LINQ Methods (LINQ to Entities)
要解决您的问题,您可以将查询的数据带到本地内存。这是使用扩展函数Enumerable.AsEnumerable()完成的。之后,您可以将您的序列用作IEnumerable。
AsEnumerable的缺点是它将查询的数据带到本地内存。如果您删除大量此类数据以创建最终结果,这将是一种浪费。因此,请确保在没有太多数据的情况下使用AsEnumerable。
幸运的是,你需要在你的最终选择中使用Split,所以你需要输入所有最终选择的数据,除非你会做Skip / Take / FirstOrDefault /等等。在这种情况下,最好限制你的选择在AsEnumerable()之前执行Skip / Take等。
我对MethodSyntax比较熟悉。 您的查询分为较小的步骤(如果需要,可以创建一个LINQ):
// still AsQueryable:
var startLocGroups = db.UberTrips
.GroupBy(uberTrip => new {uberTip.startLoc, uberTrip.geoStartLoc)
// make asEnumerable
var localStartLocGroups = startLocGroups.AsEnumerable();
// now you can do your Select
var result = localStartLocGroups
.Select(group => new LocationGroup()
{
startLocation = startLocGroup.Key.startLoc,
latitude = group.Key.geoStartLoc.Split(',')
.Count()
.ToString(),
//longitude= sgroup.Key.
countTrips = group.Count(),
});
答案 2 :(得分:-1)
由于底层Linq to Entities不支持,因此在获得数据后但返回结果之前,您必须执行此操作。
这样您可以在不调用字符串拆分功能的情况下进行查询以获取数据,然后将结果修改为正确的格式。
var data = from UberTrip in db.UberTrips
group UberTrip by new { UberTrip.startLoc, UberTrip.geoStartLoc } into startLocGroup
select new {
startLocation = startLocGroup.Key.startLoc,
geoStartLoc = startLocGroup.Key.geoStartLoc,
countTrips = startLocGroup.Count()
};
return data.Select(trip => new LocationGroup() {
startLocation = trip.startLocation,
latitude = trip.geoStartLoc.Split(',')[0],
longitude= trip.geoStartLoc.Split(',')[1],
countTrips = trip.countTrips
}).ToList();