实体框架中的数据库函数无法返回结果
我已经实现了与 Nerddinner 中相同的函数“distance Between”。我创建了一个机场存储库并具有以下方法:
public IQueryable<AllAirports> ReturnAllAirportWithIn50milesOfAPoint(double lat, double lon)
{
var airports = from d in im.AllAirports
where DistanceBetween(lat, lon, (double)d.Lat, (double)d.Lon) < 1000.00
select d;
return airports;
}
[EdmFunction("AirTravelModel.Store", "DistanceBetween")]
public static double DistanceBetween(double lat1, double long1, double lat2, double long2)
{
throw new NotImplementedException("Only call through LINQ expression");
}
当我测试它时,它显示:
base {“类型“AirTravelMVC3.Models.Repository.AirportRepository”上的指定方法“Double DistanceBetween(Double, Double, Double, Double)”无法转换为 LINQ to Entities 存储表达式,因为没有重载与传递的参数匹配。"} System.SystemException {System.NotSupportedException}
中使用了 POCO 插件。
您对为什么会发生这种情况有任何想法吗?我的工作和 nerddinner 之间的唯一区别是我在实体框架 SQL UDF如下,在数据库中运行得很好:
CREATE FUNCTION [dbo].[DistanceBetween](@Lat1 as real, @Long1 as real, @Lat2 as real, @Long2 as real) RETURNS real AS BEGIN DECLARE @dLat1InRad as float(53); SET @dLat1InRad = @Lat1 * (PI()/180.0); DECLARE @dLong1InRad as float(53); SET @dLong1InRad = @Long1 * (PI()/180.0); DECLARE @dLat2InRad as float(53); SET @dLat2InRad = @Lat2 * (PI()/180.0); DECLARE @dLong2InRad as float(53); SET @dLong2InRad = @Long2 * (PI()/180.0); DECLARE @dLongitude as float(53); SET @dLongitude = @dLong2InRad - @dLong1InRad; DECLARE @dLatitude as float(53); SET @dLatitude = @dLat2InRad - @dLat1InRad; /* Intermediate result a. */ DECLARE @a as float(53); SET @a = SQUARE (SIN (@dLatitude / 2.0)) + COS (@dLat1InRad) * COS (@dLat2InRad) * SQUARE(SIN (@dLongitude / 2.0)); /* Intermediate result c (great circle distance in Radians). */ DECLARE @c as real; SET @c = 2.0 * ATN2 (SQRT (@a), SQRT (1.0 - @a)); DECLARE @kEarthRadius as real; /* SET kEarthRadius = 3956.0 miles */ SET @kEarthRadius = 6376.5; /* kms */ DECLARE @dDistance as real; SET @dDistance = @kEarthRadius * @c; return (@dDistance); END
I have implemented the same function "distancebetween" as in Nerddinner. I created an airport repository and have these methods:
public IQueryable<AllAirports> ReturnAllAirportWithIn50milesOfAPoint(double lat, double lon)
{
var airports = from d in im.AllAirports
where DistanceBetween(lat, lon, (double)d.Lat, (double)d.Lon) < 1000.00
select d;
return airports;
}
[EdmFunction("AirTravelModel.Store", "DistanceBetween")]
public static double DistanceBetween(double lat1, double long1, double lat2, double long2)
{
throw new NotImplementedException("Only call through LINQ expression");
}
When I tested it, it shows:
base {"The specified method 'Double DistanceBetween(Double, Double, Double, Double)' on the type 'AirTravelMVC3.Models.Repository.AirportRepository' cannot be translated into a LINQ to Entities
store expression because no overload matches the passed arguments."} System.SystemException {System.NotSupportedException}
Do you have any ideas on why this happen? The only different between my work and nerddinner is that I used a POCO plugin in entity framework.
The SQL UDF is as follows, it works very well in the database:
CREATE FUNCTION [dbo].[DistanceBetween](@Lat1 as real, @Long1 as real, @Lat2 as real, @Long2 as real) RETURNS real AS BEGIN DECLARE @dLat1InRad as float(53); SET @dLat1InRad = @Lat1 * (PI()/180.0); DECLARE @dLong1InRad as float(53); SET @dLong1InRad = @Long1 * (PI()/180.0); DECLARE @dLat2InRad as float(53); SET @dLat2InRad = @Lat2 * (PI()/180.0); DECLARE @dLong2InRad as float(53); SET @dLong2InRad = @Long2 * (PI()/180.0); DECLARE @dLongitude as float(53); SET @dLongitude = @dLong2InRad - @dLong1InRad; DECLARE @dLatitude as float(53); SET @dLatitude = @dLat2InRad - @dLat1InRad; /* Intermediate result a. */ DECLARE @a as float(53); SET @a = SQUARE (SIN (@dLatitude / 2.0)) + COS (@dLat1InRad) * COS (@dLat2InRad) * SQUARE(SIN (@dLongitude / 2.0)); /* Intermediate result c (great circle distance in Radians). */ DECLARE @c as real; SET @c = 2.0 * ATN2 (SQRT (@a), SQRT (1.0 - @a)); DECLARE @kEarthRadius as real; /* SET kEarthRadius = 3956.0 miles */ SET @kEarthRadius = 6376.5; /* kms */ DECLARE @dDistance as real; SET @dDistance = @kEarthRadius * @c; return (@dDistance); END
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为了使用 POCO 和现有的 NerdDinner 源来做到这一点,我必须将其添加到 DiningRepository 类中:
In order to do this using POCOs with the existing NerdDinner source I had to add this to the DinnerRepository class:
假设 DistanceBetween 在 c# 中实现 问题(如 @p.campbell 暗示)是查询生成器不知道如何计算 DistanceBetween
要让您的代码按原样工作,您可能需要执行类似
ToList( ) 将强制 AllAirports 计算为一个列表,然后可以使用您的 C# 函数在内存中计算它。显然这不会扩展到大量机场。如果这是一个问题,您可能需要执行一个粗略的“框”查询,只需执行一个廉价的方内表达式即可返回少量机场、ToList,然后调用您的 distance Between 来优化结果。
Assuming DistanceBetween is implemented in c# The issue (as hinted at by @p.campbell) is that the query generator doesn't know how to calculate DistanceBetween
To get your code to work as is, you might need to do something like
the ToList() will force the AllAirports to evaluate to a list, then it can be evaluated in memory, using your c# function. Obviously this won't scale to a huge number of airports. If that was an issue, you might want to do a rough "box" query where you just do a cheap within-a-square expression to return a small number of airports, ToList that, and then call your distancebetween to refine the results.
在对数据库架构进行多次更改并“从数据库更新模型”后,我遇到了同样的异常。
将我的 EDMX XML 与 Nerddinner 的原始 XML 进行比较后,我发现我的 EDMX XML 已将 DistanceBetween 函数的所有类型更改为“真实”,其中 NerdDinner 具有“浮动”。将它们改回浮动解决了问题。
I got this same exception after I made several changes to the DB schema and "updated the model from database".
After comparing my EDMX XML with the original from Nerd Dinner, I saw that mine had changed all of the types for the DistanceBetween function to "real", where Nerd Dinner had "float". Changing them back to float resolved the issue.